abstractcachableoperator.java

来自「Rapla是一个灵活的多用户资源管理系统。它提供的一些功能有:日历GUI」· Java 代码 · 共 914 行 · 第 1/3 页

JAVA
914
字号
        if (storageUpdateListeners.size() == 0)
            return;
        StorageUpdateListener[] listeners = getStorageUpdateListeners();
        for (int i = 0;i<listeners.length; i++) {
            listeners[i].storageDisconnected();
        }
    }



    public Date today() {
        return today;
    }

    // End of StorateOperator interface
    protected void checkConnected() throws RaplaException {
        if (!isConnected())
            throw new RaplaException(getI18n().format("error.connection_closed",""));
    }
    public void setCache( final LocalCache cache) throws RaplaException {
        this.cache = cache;
        idTable.setCache( cache );
    }

    public LocalCache getCache() {
        return cache;
    }

    /** Override this method to implement the persistent mechanism.
        By default it calls
        <li>check()</li>
        <li>update()</li>
        <li>fireStorageUpdate()</li>
        <li>fireTriggerEvents()</li>
        You should not call dispatch directly from the client.
        Use storeObjects and removeObjects instead.
    */
    public void dispatch(final UpdateEvent evt) throws RaplaException {
        UpdateEvent closure = createClosure( evt);
        check( closure );
        UpdateResult result = update( closure, true);
        fireStorageUpdated( result );
    }

    /** performs Integrety constraints check */
    protected void check(final UpdateEvent evt) throws RaplaException {
        Set storeObjects = new HashSet(evt.getStoreObjects());
        Set removeObjects = new HashSet(evt.getRemoveObjects());
        checkUnique( storeObjects );
        checkConsistency( storeObjects );
        checkReferences( storeObjects );
        checkNoDependencies( removeObjects );
        checkVersions( storeObjects );
    }
    
    
    /** Writes the UpdateEvent in the cache */
    protected UpdateResult update(final UpdateEvent evt, final boolean increaseVersion) throws RaplaException {
        User user = null;
        if ( evt.getUserId() != null) {
            user = (User) resolveId( evt.getUserId() );
        }
        UpdateResult result = new UpdateResult( user );

        List resolvableEntities = new ArrayList();
        HashMap oldEntities = new HashMap();
        // First make a copy of the old entities
        for (Iterator it = evt.getStoreObjects().iterator(); it.hasNext();)
        {
            RefEntity entity = (RefEntity) it.next();
            RefEntity persistantEntity = findPersistantVersion( entity );

            // do nothing, because the persitantVersion is the same as the stored
            if ( persistantEntity == entity ) {
                continue;
            }

            if (persistantEntity != null  ) {
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Storing old: " + entity);

                RefEntity oldEntity = (RefEntity)persistantEntity.deepClone();
                oldEntities.put( persistantEntity, oldEntity );
            }
        }
        // Then update the new entities
        for (Iterator it = evt.getStoreObjects().iterator(); it.hasNext();)
        {
            RefEntity entity = (RefEntity) it.next();
            if ( increaseVersion )
                increaseVersion( entity );
            RefEntity persistantEntity = findPersistantVersion( entity );

            // do nothing, because the persitantVersion is always ReadOnly
            if ( persistantEntity == entity ) {
                continue;
            }

            if (persistantEntity != null  ) {
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Changing: " + entity);

                ((Mementable)persistantEntity).copy(entity);
            } else {
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Adding entity: " + entity);

                persistantEntity = (RefEntity)entity.deepClone();
            }
            ((SimpleEntity)persistantEntity).setReadOnly( true );
            cache.put(persistantEntity);
            resolvableEntities.add( persistantEntity );
        }

        /** we need to update every reference in the stored entity.
         * So that the references in the persistant entities always point to persistant entities and never
         * to local working copies*/
        for (Iterator it = resolvableEntities.iterator(); it.hasNext();)
        {
            SimpleEntity persistantEntity = (SimpleEntity) it.next();
            persistantEntity.resolveEntities( getCache());

            RefEntity newEntity = (RefEntity)persistantEntity.deepClone();
            RefEntity oldEntity = (RefEntity)oldEntities.get( persistantEntity );
            if ( oldEntity != null) {
                result.addOperation( new UpdateResult.Change( persistantEntity, newEntity, oldEntity));
            } else {
                result.addOperation( new UpdateResult.Add( persistantEntity,  newEntity));
            }
        }

        for (Iterator it = evt.getRemoveObjects().iterator(); it.hasNext();)
        {
            RefEntity entity = (RefEntity) it.next();
            if ( increaseVersion )
                increaseVersion( entity );
            RefEntity persistantVersion =  findPersistantVersion( entity );

            if (persistantVersion != null) {
                cache.remove( persistantVersion );
                ((SimpleEntity)persistantVersion).setReadOnly( true );
                result.addOperation( new UpdateResult.Remove( persistantVersion));
            }
        }
        return result;
    }

    /** Create a closure for all objects that should be updated. The closure
        contains all objects that are sub-entities of the entities and all objects
        and all other objects that are affected by the update: e.g.
        Classifiables when the DynamicType changes.
        The method will recursivly proceed with all discovered objects.
    */
    protected UpdateEvent createClosure(final UpdateEvent evt) throws RaplaException {
        UpdateEvent closure = (UpdateEvent) evt.clone();
        Iterator it = evt.getStoreObjects().iterator();
        while (it.hasNext())
        {
            addStoreOperationsToClosure(closure, (RefEntity) it.next());
        }

        it = evt.getRemoveObjects().iterator();
        while (it.hasNext())
        {
            addRemoveOperationsToClosure(closure,(RefEntity) it.next() );
        }
        return closure;
    }

    private void increaseVersion(RefEntity e) throws RaplaException {
        e.setVersion (e.getVersion () + 1);
        if (getLogger().isDebugEnabled())
              getLogger().debug("Increasing Version for " + e + " to " + e.getVersion());
    }

    private void addStoreOperationsToClosure(UpdateEvent evt,RefEntity entity) throws RaplaException {
        if (getLogger().isDebugEnabled() && !evt.getStoreObjects().contains(entity))
            getLogger().debug("Adding " + entity + " to store closure");
        evt.putStore(entity);
        if (DynamicType.TYPE.equals( entity.getRaplaType())) {
            DynamicType dynamicType = (DynamicType) entity;
            addChangedDynamicTypeDependant(evt, dynamicType);
        }

        Iterator it = entity.getSubEntities();

        while (it.hasNext()) {
            RefEntity subEntity = (RefEntity)it.next();
            addStoreOperationsToClosure(evt,subEntity);
        }

        it = getRemovedEntities(entity).iterator();
        while (it.hasNext()) {
            addRemoveOperationsToClosure(evt,(RefEntity)it.next());
        }
    }

    private void addChangedDynamicTypeDependant(UpdateEvent evt,DynamicType type) throws RaplaException {
    	Iterator it = getReferencingEntities((RefEntity)type).iterator();
        while (it.hasNext()) {
            DynamicTypeDependant dependant = (DynamicTypeDependant) it.next();
            //  Classifiables need update?
            if ( ! dependant.needsChange(type) )
                continue;
            if (getLogger().isDebugEnabled())
                getLogger().debug("Classifiable " + dependant + " needs change!");
            // Classifiables are allready on the store list
            if ( evt.getStoreObjects().contains( dependant ) )
            {
                dependant =  (DynamicTypeDependant)evt.findEntity( (RefEntity) dependant );
            }
            // no, then create a clone of the classfiable object and add to list
            else
            {
                User user = null;
                if ( evt.getUserId() != null)
                {
                    user = (User) resolveId( evt.getUserId());
                }
                dependant =  (DynamicTypeDependant)editObject( (Entity) dependant, user);
                addStoreOperationsToClosure(evt,(RefEntity) dependant);
            }
            dependant.commitChange(type);
        }
    }

     private void addRemoveOperationsToClosure(UpdateEvent evt,RefEntity entity) throws RaplaException {
        if (getLogger().isDebugEnabled() && !evt.getRemoveObjects().contains(entity))
            getLogger().debug("Adding " + entity + " to remove closure");
        evt.putRemove(entity);

        // add the subentities
        Iterator it = entity.getSubEntities();
        while (it.hasNext()) {
            addRemoveOperationsToClosure(evt,(RefEntity)it.next());
        }

        // And also add the SubEntities that have been removed, before storing
        it = getRemovedEntities(entity).iterator();
        while (it.hasNext()) {
            addRemoveOperationsToClosure(evt,(RefEntity)it.next());
        }

        // If entity is a user, remove the preference object
        if (User.TYPE.equals( entity.getRaplaType() )) {
            Preferences preferences = cache.getPreferences((User) entity);
            if (preferences != null)
                addRemoveOperationsToClosure(evt,(RefEntity)preferences);
        }


    }

    private Collection getRemovedEntities( RefEntity entity ) {
        RefEntity original = findPersistantVersion( entity );
        List result = null;
        if ( original != null ) {
            Iterator it = original.getSubEntities();
            while ( it.hasNext()) {
                RefEntity subEntity = (RefEntity) it.next();
                if ( !entity.isParentEntity( subEntity) ) {
                    // SubEntity not found in the new entity add it to remove List
                    if ( result == null) {
                        result = new ArrayList();
                    }
                    result.add(subEntity);
                    //System.out.println( "Removed " + subEntity);
                }
            }
        }
        if ( result != null) {
            return result;
        } else {
            return Tools.EMPTY_SET;
        }
    }

    private void throwNotUnique(RefEntity entity,String name) throws UniqueKeyException {
        throw new UniqueKeyException(i18n.format("error.not_unique"
                                                 ,name)
                                     );
    }

    public Entity getPersistant(Entity entity) throws EntityNotFoundException {
        RefEntity persistant = findPersistantVersion( (RefEntity)entity );
        if ( persistant == null) {
            throw new EntityNotFoundException("There is no persistant version of " + entity);
        }
        return persistant;
    }

    protected void resolveEntities(Iterator entities, EntityResolver resolver) throws RaplaException {
        List readOnlyList = new ArrayList();
        for (Iterator it = entities;it.hasNext();) {
            Object obj = it.next();
            if ( obj instanceof RefEntity) {
            	RefEntity entity = (RefEntity)obj;
                entity.resolveEntities( resolver);
                readOnlyList.add( obj );
            }
        }
        for (Iterator it = readOnlyList.iterator();it.hasNext();)
        {
            ((SimpleEntity)it.next()).setReadOnly( true );
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?