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 + -
显示快捷键?