OpenInspectSessionsHandler : handler for opening the inspect session dialog
[taxeditor.git] / eu.etaxonomy.taxeditor.cdmlib / src / main / java / eu / etaxonomy / taxeditor / remoting / cache / CdmTransientEntityCacher.java
index a5146bf31e28256fc5a80e85b907a7d675bbd68e..7899e338a22990f571d81cbea65596b08c10b301 100644 (file)
@@ -9,16 +9,11 @@
  */
 package eu.etaxonomy.taxeditor.remoting.cache;
 
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
-import javassist.util.proxy.ProxyFactory;
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.Element;
 import net.sf.ehcache.config.CacheConfiguration;
@@ -27,12 +22,9 @@ import net.sf.ehcache.statistics.LiveCacheStatistics;
 import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
 
 import org.apache.log4j.Logger;
-import org.hibernate.collection.spi.PersistentCollection;
-import org.hibernate.proxy.HibernateProxy;
-import org.hibernate.proxy.LazyInitializer;
-import org.springframework.util.ReflectionUtils;
 
 import eu.etaxonomy.cdm.api.cache.CdmServiceCacher;
+import eu.etaxonomy.cdm.model.ICdmCacher;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
 
@@ -50,22 +42,22 @@ import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
  *
  */
 
-public class CdmTransientEntityCacher  {
+public class CdmTransientEntityCacher implements ICdmCacher {
 
     private static final Logger logger = Logger.getLogger(CdmTransientEntityCacher.class);
 
 
-    private ICdmEntitySessionManager cdmEntitySessionManager;
+    private final ICdmEntitySessionManager cdmEntitySessionManager;
 
     private static CdmServiceCacher cdmServiceCacher;
 
-    private String cacheId;
+    private final String cacheId;
 
-    private Cache cache;
+    private final Cache cache;
+
+    private final CacheLoader cacheLoader;
 
-    private Cache cdmlibModelCache;
 
-    private static boolean isRecursiveEnabled = true;
 
     public static enum CollectionType {
         SET,
@@ -78,17 +70,14 @@ public class CdmTransientEntityCacher  {
         }
     }
 
-    private CdmTransientEntityCacher() {
-
-    }
 
     public CdmTransientEntityCacher(String cacheId, ICdmEntitySessionManager cdmEntitySessionManager) {
         this.cacheId = cacheId;
 
         cache = new Cache(getEntityCacheConfiguration(cacheId));
-        cdmServiceCacher.getDefaultCacheManager().addCache(cache);
+        CdmRemoteCacheManager.getInstance().getDefaultCacheManager().addCache(cache);
 
-        cdmlibModelCache = CdmRemoteCacheManager.getInstance().getCdmModelGetMethodsCache();
+        cacheLoader = new CacheLoader(this);
         this.cdmEntitySessionManager = cdmEntitySessionManager;
 
 
@@ -137,334 +126,40 @@ public class CdmTransientEntityCacher  {
      * @return
      */
     private Cache getCache() {
-        return cdmServiceCacher.getDefaultCacheManager().getCache(cacheId);
+        return  CdmRemoteCacheManager.getInstance().getDefaultCacheManager().getCache(cacheId);
     }
 
-    @SuppressWarnings("unchecked")
     public <T extends Object> T load(T obj, boolean recursive) {
-        if(obj == null) {
-            return null;
-        }
-        if(obj instanceof CdmBase) {
-            return (T) load((CdmBase)obj, recursive);
-        } else if (obj instanceof Map) {
-            return (T) load((Map<T,T>)obj, recursive);
-        } else if (obj instanceof Collection) {
-            return (T) load((Collection<T>)obj, recursive);
-        }
-
-        return obj;
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T extends Object> T loadRecursive(T obj, Set<CdmBase> alreadyVisitedEntities) {
-        if(obj == null) {
-            return null;
-        }
-        if(obj instanceof CdmBase) {
-            return (T) loadRecursive((CdmBase)obj, alreadyVisitedEntities);
-        } else if (obj instanceof Map) {
-            return (T) load((Map<T,T>)obj, alreadyVisitedEntities);
-        } else if (obj instanceof Collection) {
-            return (T) load((Collection<T>)obj, alreadyVisitedEntities);
-        }
-
-
-        logger.info("No caching yet for type " + obj.getClass().getName());
-
-        return obj;
+        return cacheLoader.load(obj, recursive);
     }
 
     public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive){
-        if(map == null) {
-            return null;
-        }
-
-        if(isRecursiveEnabled && recursive) {
-            logger.info("---- starting recursive load for cdm entity map");
-            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
-            Map<T,T> cachedMap = load(map, alreadyVisitedEntities);
-            alreadyVisitedEntities.clear();
-            logger.info("---- ending recursive load for cdm entity map \n");
-            return cachedMap;
-        } else {
-            return load(map, null);
-        }
-    }
-
-
-    private <T extends Object> Map<T,T> load(Map<T,T> map, Set<CdmBase> alreadyVisitedEntities){
-        if(map == null || map.isEmpty()) {
-            return map;
-        }
-
-        int originalMapSize = map.size();
-        Object[] result = new Object[ map.size() * 2 ];
-        Iterator<Map.Entry<T,T>> iter = map.entrySet().iterator();
-        int i=0;
-        while ( iter.hasNext() ) {
-            Map.Entry<T,T> e = iter.next();
-            result[i++] = e.getKey();
-            result[i++] = e.getValue();
-        }
-
-        for(i=0; i<result.length;i++) {
-            if(alreadyVisitedEntities == null) {
-                result[i] = load(result[i], false);
-            } else {
-                result[i] = loadRecursive(result[i], alreadyVisitedEntities);
-            }
-        }
-        map.clear();
-        for(i = 0; i < originalMapSize; i+=2 ) {
-            map.put(
-                    (T)result[i],
-                    (T)result[i+1]
-                    );
-        }
-        return map;
+        return cacheLoader.load(map, recursive);
     }
 
     public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive){
-        if(collection == null) {
-            return null;
-        }
-
-        Collection<T> loadedCollection;
-        if(isRecursiveEnabled && recursive) {
-            logger.info("---- starting recursive load for cdm entity collection");
-            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
-            Collection<T> cachedCollection = load(collection, alreadyVisitedEntities);
-            alreadyVisitedEntities.clear();
-            logger.info("---- ending recursive load for cdm entity collection \n");
-            loadedCollection = cachedCollection;
-        } else {
-            loadedCollection = load(collection, null);
-        }
-        return loadedCollection;
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T extends Object> Collection<T> load(Collection<T> collection, Set<CdmBase> alreadyVisitedEntities){
-        int length = collection.size();
-        Object[] result = new Object[length];
-        Iterator<T> collectionItr = collection.iterator();
-        int count = 0;
-        while(collectionItr.hasNext()) {
-            Object obj = collectionItr.next();
-            if(alreadyVisitedEntities == null) {
-                result[count] = load(obj, false);
-            } else {
-                result[count] = loadRecursive(obj, alreadyVisitedEntities);
-            }
-
-            count++;
-        }
-
-        collection.clear();
-
-        for ( int i = 0; i < length; i++ ) {
-            collection.add((T)result[i]);
-        }
-
-        return collection;
+        return cacheLoader.load(collection, recursive);
     }
 
-
-    /**
-     * Puts the (Key,Value) pair of ({@link java.util.UUID}, {@link eu.etaxonomy.cdm.model.common.CdmBase}),
-     * in the cache corresponding to the given cache id
-     *
-     * @param cacheId
-     * @param uuid
-     * @param cdmEntity
-     */
     public CdmBase load(CdmBase cdmEntity, boolean recursive) {
-        if(cdmEntity == null) {
-            return null;
-        }
-
-
-        // start by looking up the cdm entity in the cache
-        CdmBase cachedCdmEntity = getFromCache(cdmEntity);
-
-        if(cachedCdmEntity != null) {
-            // if cdm entity was found in cache then
-            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
-            // .. return if the cached and input objects are identical, else (this is a newly loaded object so) continue
-            if(cachedCdmEntity == cdmEntity) {
-                return cachedCdmEntity;
-            }
-        }
-
-        CdmBase loadedCdmBase;
-        if(isRecursiveEnabled && recursive) {
-            logger.info("---- starting recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
-            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
-            CdmBase cb =  loadRecursive(cdmEntity, alreadyVisitedEntities);
-            alreadyVisitedEntities.clear();
-            logger.info("---- ending recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + "\n");
-            loadedCdmBase =  cb;
-        } else {
-            loadedCdmBase = load(cdmEntity);
-        }
-        return loadedCdmBase;
-
-    }
-
-
-    private CdmBase load(CdmBase cdmEntity) {
-        logger.info("loading object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
-
-        // start by looking up the cdm entity in the cache
-        CdmBase cachedCdmEntity = getFromCache(cdmEntity);
-
-        if(cachedCdmEntity != null) {
-            // if cdm entity was found in cache then return ...
-            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
-            return cachedCdmEntity;
-        } else {
-            // ... else save the entity in the cache
-            getCache().put(new Element(generateKey(cdmEntity), cdmEntity));
-            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " put in cache");
-            return cdmEntity;
-        }
+        return cacheLoader.load(cdmEntity, recursive);
     }
 
-    private CdmBase loadRecursive(CdmBase cdmEntity, Set<CdmBase> alreadyVisitedEntities) {
-
-        CdmBase cachedCdmEntity = load(cdmEntity);
-
-        // we want to recursive through the cdmEntity (and not the cachedCdmEntity)
-        // since there could be new or deleted objects in the cdmEntity sub-graph
-
-        // start by getting the fields from the cdm entity
-        String className = cdmEntity.getClass().getName();
-        CdmModelFieldPropertyFromClass cmgmfc = getFromCdmlibModelCache(className);
-        if(cmgmfc != null) {
-            alreadyVisitedEntities.add(cdmEntity);
-            List<String> fields = cmgmfc.getFields();
-            for(String field : fields) {
-                // retrieve the actual object corresponding to the field.
-                // this object will be either a CdmBase or a Collection / Map
-                // with CdmBase as the generic type
-
-                CdmBase cdmEntityInSubGraph = getCdmBaseTypeFieldValue(cdmEntity, cachedCdmEntity, field, alreadyVisitedEntities);
-                if(cdmEntityInSubGraph != null) {
-                    if(!alreadyVisitedEntities.contains(cdmEntityInSubGraph)) {
-                        logger.info("recursive loading object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
-                        loadRecursive(cdmEntityInSubGraph, alreadyVisitedEntities);
-                    } else {
-                        logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
-                    }
-                }
-            }
-        } else {
-            throw new CdmClientCacheException("CdmEntity with class " + cdmEntity.getClass().getName() + " is not found in the cdmlib model cache. " +
-                    "The cache may be corrupted or not in sync with the latest model version" );
-        }
-        return cachedCdmEntity;
+    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
+        return cacheLoader.getFromCdmlibModelCache(className);
     }
 
 
-    private CdmBase getCdmBaseTypeFieldValue(CdmBase cdmEntity,
-            CdmBase cachedCdmEntity,
-            String fieldName,
-            Set<CdmBase> alreadyVisitedEntities) {
-
-        // this method attempts to make sure that for any two objects found in
-        // the object graph, if they are equal then they should also be the same,
-        // which is crucial for the merge to work
-        if(cachedCdmEntity == null) {
-            throw new CdmClientCacheException("When trying to set field value, the cached cdm entity cannot be null");
-        }
-
-        Class<?> clazz = cdmEntity.getClass();
-        try {
-            // this call will search in the provided class as well as
-            // the super classes until it finds the field
-            Field field = ReflectionUtils.findField(clazz, fieldName);
-
-            if(field == null) {
-                throw new CdmClientCacheException("Field '" + fieldName
-                        + "' not found when searching in class '" + clazz.getName() + "' and its supercalsses");
-            }
-            field.setAccessible(true);
-            Object o = field.get(cdmEntity);
-
-            if(o != null && o instanceof HibernateProxy) {
-                LazyInitializer hli = ((HibernateProxy)o).getHibernateLazyInitializer();
-                if(!hli.isUninitialized()) {
-                    o = ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation();
-                    field.set(cdmEntity, o);
-                }
-            }
-
-            if(o != null && o instanceof PersistentCollection) {
-                PersistentCollection pc = ((PersistentCollection)o);
-                if(pc.wasInitialized()) {
-                    o = ProxyUtils.getObject(pc);
-                    field.set(cdmEntity, o);
-                }
-            }
-
-            //field.set(cdmEntity, o);
-            CdmBase cdmEntityInSubGraph = null;
-            if(o != null
-                    && !ProxyFactory.isProxyClass(o.getClass())
-                    && !(o instanceof PersistentCollection)    ) {
-
-                if(CdmBase.class.isAssignableFrom(o.getClass())) {
-                    logger.info("found initialised cdm entity '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
-                    cdmEntityInSubGraph  = (CdmBase)o;
-                    CdmBase cachedCdmEntityInSubGraph = getFromCache(cdmEntityInSubGraph);
-                    // making sure that the field in cached cdm entity is always
-                    // up-to-date by setting to the value of the cdm entity being loaded
-                    // the only execption to this is found below
-                    field.set(cachedCdmEntity, o);
-
-                    // the only exception to updating the field to the latest value
-                    // is the case where the field has been already initialised, cached and
-                    // is not the same as the one in the cache, in which case we set the value
-                    // of the field to the one found in the cache
-                    if(cachedCdmEntityInSubGraph != null) {
-                        if(cachedCdmEntityInSubGraph != cdmEntityInSubGraph) {
-                            logger.info("setting cached + real value to '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
-                            field.set(cachedCdmEntity, cachedCdmEntityInSubGraph);
-                        }
-                    }
-                } else if(o instanceof Map) {
-                    loadRecursive((Map)o, alreadyVisitedEntities);
-                } else if(o instanceof Collection) {
-                    loadRecursive((Collection)o, alreadyVisitedEntities);
-                }
-            }
-            // we return the original cdm entity in the sub graph because we
-            // want to continue to recurse on the input cdm entity graph
-            // and not the one in the cache
-            return cdmEntityInSubGraph;
-        } catch (SecurityException e) {
-            throw new CdmClientCacheException(e);
-        } catch (IllegalArgumentException e) {
-            throw new CdmClientCacheException(e);
-        } catch (IllegalAccessException e) {
-            throw new CdmClientCacheException(e);
-        }
-    }
 
 
+    @Override
     public void put(CdmBase cdmEntity) {
         CdmEntityCacheKey id = new CdmEntityCacheKey(cdmEntity);
-        Element cachedCdmEntityElement = getCacheElement(id);
-
-        if(cachedCdmEntityElement == null) {
-            cachedCdmEntityElement = cdmServiceCacher.getCacheElement(cdmEntity.getUuid());
-            if(cachedCdmEntityElement != null) {
-                logger.info("Cdm Entity with id : " + cdmEntity.getId() + " already exists in permanent cache. Ignoring put.");
-                return;
-            }
+        Element cachedCdmEntityElement = cdmServiceCacher.getCacheElement(cdmEntity.getUuid());
+        if(cachedCdmEntityElement != null) {
+            logger.info("Cdm Entity with id : " + cdmEntity.getId() + " already exists in permanent cache. Ignoring put.");
+            return;
         }
-
         getCache().put(new Element(id, cdmEntity));
     }
 
@@ -473,14 +168,6 @@ public class CdmTransientEntityCacher  {
         return getCache().get(key);
     }
 
-    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
-        Element e = cdmlibModelCache.get(className);
-        if (e == null) {
-            return null;
-        } else {
-            return (CdmModelFieldPropertyFromClass) e.getObjectValue();
-        }
-    }
 
     public CdmBase getFromCache(CdmEntityCacheKey id) {
         Element e = getCacheElement(id);
@@ -496,6 +183,7 @@ public class CdmTransientEntityCacher  {
         return getFromCache(cacheId);
     }
 
+    @Override
     public CdmBase getFromCache(CdmBase cdmBase) {
 
         CdmEntityCacheKey cacheId = generateKey(cdmBase);
@@ -540,7 +228,7 @@ public class CdmTransientEntityCacher  {
     public void dispose() {
         cache.removeAll();
         cache.flush();
-        cdmServiceCacher.getDefaultCacheManager().removeCache(cacheId);
+        CdmRemoteCacheManager.getInstance().getDefaultCacheManager().removeCache(cacheId);
     }
 
 
@@ -555,14 +243,6 @@ public class CdmTransientEntityCacher  {
         return new CdmEntityCacheKey(entityClass, id);
     }
 
-    public static boolean isRecursiveEnabled() {
-        return isRecursiveEnabled;
-    }
-
-    public static void  setRecursiveEnabled(boolean ire) {
-        isRecursiveEnabled = ire;
-    }
-
 
 
 }