AbstractPersistentCollection : fixed loading of collection
authorCherian Mathew <c.mathew@bgbm.org>
Mon, 2 Mar 2015 09:21:23 +0000 (09:21 +0000)
committerCherian Mathew <c.mathew@bgbm.org>
Mon, 2 Mar 2015 09:21:23 +0000 (09:21 +0000)
MockCdmEntitySessionManager, MockCdmEntitySession, ICdmEntitySessionManager, ICdmEntitySession, CdmEntitySessionManager,
CdmEntitySession : added new load method with choice to update client object graph
TermServiceRequestExecutor : using cacher instead of cache
ICachedCommonService, CachedCommonServiceImpl, ProxyUtils : moved utility methods to utility class
CdmServiceRequestExecutor : updating client object graph when calling merge
EntityCacherDebugResult : corrections for output string
CdmTransientEntityCacher : corrected cache configuration, added load methods with update choice, added service cacher check before put
CacheLoader : checking in recursive call if collection and maps are already visited
CdmRemotingException : added constructor with exception as argument
CdmServiceCacher : corrected cache configuration and loading of entities from default cache

17 files changed:
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/api/cache/CdmServiceCacher.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/CdmRemotingException.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CacheLoader.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CdmTransientEntityCacher.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/EntityCacherDebugResult.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/ProxyUtils.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/service/CachedCommonServiceImpl.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/service/CdmServiceRequestExecutor.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/service/ICachedCommonService.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/service/TermServiceRequestExecutor.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/CdmEntitySession.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/CdmEntitySessionManager.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/ICdmEntitySession.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/ICdmEntitySessionManager.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/mock/MockCdmEntitySession.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/mock/MockCdmEntitySessionManager.java
eu.etaxonomy.taxeditor.cdmlib/src/main/java/org/hibernate/collection/internal/AbstractPersistentCollection.java

index d3d6aca862fdda607be3750dbc1840330bd5a41e..0239a7e82bf36e3a11b26cdc49ef7c01ac702873 100644 (file)
@@ -2,6 +2,9 @@ package eu.etaxonomy.cdm.api.cache;
 
 import java.util.UUID;
 
+import net.sf.ehcache.config.CacheConfiguration;
+import net.sf.ehcache.config.SizeOfPolicyConfiguration;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -10,6 +13,7 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
 import eu.etaxonomy.taxeditor.remoting.cache.CacheLoader;
 import eu.etaxonomy.taxeditor.remoting.cache.CdmTransientEntityCacher;
+import eu.etaxonomy.taxeditor.service.TermServiceRequestExecutor;
 
 /**
  * Class which uses CDM services to cache cdm entities
@@ -25,24 +29,41 @@ import eu.etaxonomy.taxeditor.remoting.cache.CdmTransientEntityCacher;
 @Component
 public class CdmServiceCacher extends CdmCacher{
 
-       @Autowired
-       ITermService termService;
+    @Autowired
+    ITermService termService;
 
-       private CacheLoader cacheLoader;
+    private CacheLoader cacheLoader;
 
-       @Override
-       protected void setup() {
-           DefinedTermBase.setCacher(this);
-               CdmTransientEntityCacher.setDefaultCacher(this);
-               cacheLoader = new CacheLoader(this);
-       }
+    @Override
+    protected void setup() {
+        DefinedTermBase.setCacher(this);
+        CdmTransientEntityCacher.setDefaultCacher(this);
+        TermServiceRequestExecutor.setDefaultCacher(this);
+        cacheLoader = new CacheLoader(this);
+    }
+
+    @Override
+    protected CacheConfiguration getDefaultCacheConfiguration() {
+        // For a better understanding on how to size caches, refer to
+        // http://ehcache.org/documentation/configuration/cache-size
 
-       @Override
-       protected CdmBase findByUuid(UUID uuid) {
-               CdmBase term = termService.findWithoutFlush(uuid);
-               return cacheLoader.load(term, true);
+        SizeOfPolicyConfiguration sizeOfConfig = new SizeOfPolicyConfiguration();
+        sizeOfConfig.setMaxDepth(100);
+        sizeOfConfig.setMaxDepthExceededBehavior("abort");
 
-       }
+        return new CacheConfiguration(DEFAULT_CACHE_NAME, 0)
+        .eternal(true)
+        .statistics(true)
+        .sizeOfPolicy(sizeOfConfig)
+        .overflowToOffHeap(false);
+
+    }
+
+    @Override
+    protected CdmBase findByUuid(UUID uuid) {
+        CdmBase term = termService.findWithoutFlush(uuid);
+        return load(term);
+    }
 
     /* (non-Javadoc)
      * @see eu.etaxonomy.cdm.model.ICdmCacher#isCachable(eu.etaxonomy.cdm.model.common.CdmBase)
@@ -56,4 +77,21 @@ public class CdmServiceCacher extends CdmCacher{
     }
 
 
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.cache.CdmCacher#load(eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
+    public CdmBase load(CdmBase cdmEntity) {
+        CdmBase cachedCdmEntity = getFromCache(cdmEntity);
+        // NOTE : only when no cached cdm entity exists we
+        // load the entire sub-graph, which means that the
+        // sub-graph is never updated if the input
+        // cdm entity graph is newer
+        if(cachedCdmEntity == null && isCachable(cdmEntity)) {
+            cachedCdmEntity =  cacheLoader.load(cdmEntity, true, false);
+        }
+        return cachedCdmEntity;
+    }
+
+
 }
index 68f5ca01f3fee95e103237d2b27996c4e2b0a1c9..13fcb4fcd417f085528dd7b0ce8baec0a2a4922c 100644 (file)
@@ -1,9 +1,9 @@
 package eu.etaxonomy.taxeditor.remoting;
 
 public class CdmRemotingException extends RuntimeException {
-       
+
        /**
-        * 
+        *
         */
        private static final long serialVersionUID = -560332689478356360L;
 
@@ -11,4 +11,8 @@ public class CdmRemotingException extends RuntimeException {
                super(message);
        }
 
+       public CdmRemotingException(Exception exception) {
+           super(exception);
+       }
+
 }
index cb2879abc8f90ecca99d412aaea4d8c5499262b7..642437932235f9d4f987ab512fa5b1265708dfd7 100644 (file)
@@ -44,10 +44,17 @@ public class CacheLoader {
 
     private final Cache cdmlibModelCache;
 
+    private final ICdmCacher cdmServiceCacher;
+
 
     public CacheLoader(ICdmCacher cdmCacher) {
+        this(cdmCacher, null);
+    }
+
+    public CacheLoader(ICdmCacher cdmCacher, ICdmCacher cdmServiceCacher) {
         this.cdmCacher = cdmCacher;
         this.cdmlibModelCache = CdmRemoteCacheManager.getInstance().getCdmModelGetMethodsCache();
+        this.cdmServiceCacher = cdmServiceCacher;
     }
 
 
@@ -61,32 +68,32 @@ public class CacheLoader {
     }
 
     @SuppressWarnings("unchecked")
-    public <T extends Object> T load(T obj, boolean recursive) {
+    public <T extends Object> T load(T obj, boolean recursive, boolean update) {
         if(obj == null) {
             return null;
         }
         if(obj instanceof CdmBase) {
-            return (T) load((CdmBase)obj, recursive);
+            return (T) load((CdmBase)obj, recursive, update);
         } else if (obj instanceof Map) {
-            return (T) load((Map<T,T>)obj, recursive);
+            return (T) load((Map<T,T>)obj, recursive, update);
         } else if (obj instanceof Collection) {
-            return (T) load((Collection<T>)obj, recursive);
+            return (T) load((Collection<T>)obj, recursive, update);
         }
 
         return obj;
     }
 
     @SuppressWarnings("unchecked")
-    private <T extends Object> T loadRecursive(T obj, Set<CdmBase> alreadyVisitedEntities) {
+    private <T extends Object> T loadRecursive(T obj, Set<Object> alreadyVisitedEntities, boolean update) {
         if(obj == null) {
             return null;
         }
         if(obj instanceof CdmBase) {
-            return (T) loadRecursive((CdmBase)obj, alreadyVisitedEntities);
+            return (T) loadRecursive((CdmBase)obj, alreadyVisitedEntities, update);
         } else if (obj instanceof Map) {
-            return (T) load((Map<T,T>)obj, alreadyVisitedEntities);
+            return (T) load((Map<T,T>)obj, alreadyVisitedEntities, update);
         } else if (obj instanceof Collection) {
-            return (T) load((Collection<T>)obj, alreadyVisitedEntities);
+            return (T) load((Collection<T>)obj, alreadyVisitedEntities, update);
         }
 
 
@@ -95,25 +102,25 @@ public class CacheLoader {
         return obj;
     }
 
-    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive){
-        if(map == null) {
-            return null;
-        }
+    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive, boolean update){
+
 
         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);
+            Set<Object> alreadyVisitedEntities = new HashSet<Object>();
+            Map<T,T> cachedMap = load(map, alreadyVisitedEntities, update);
             alreadyVisitedEntities.clear();
             logger.info("---- ending recursive load for cdm entity map \n");
             return cachedMap;
         } else {
-            return load(map, null);
+            return load(map, null, update);
         }
     }
 
 
-    private <T extends Object> Map<T,T> load(Map<T,T> map, Set<CdmBase> alreadyVisitedEntities){
+    private <T extends Object> Map<T,T> load(Map<T,T> map, Set<Object> alreadyVisitedEntities, boolean update){
+        //map = (Map<T,T>)deproxy(map);
+
         if(map == null || map.isEmpty()) {
             return map;
         }
@@ -122,6 +129,8 @@ public class CacheLoader {
         Object[] result = new Object[ map.size() * 2 ];
         Iterator<Map.Entry<T,T>> iter = map.entrySet().iterator();
         int i=0;
+        // to avoid ConcurrentModificationException
+        alreadyVisitedEntities.add(map);
         while ( iter.hasNext() ) {
             Map.Entry<T,T> e = iter.next();
             result[i++] = e.getKey();
@@ -130,9 +139,9 @@ public class CacheLoader {
 
         for(i=0; i<result.length;i++) {
             if(alreadyVisitedEntities == null) {
-                result[i] = load(result[i], false);
+                result[i] = load(result[i], false, update);
             } else {
-                result[i] = loadRecursive(result[i], alreadyVisitedEntities);
+                result[i] = loadRecursive(result[i], alreadyVisitedEntities, update);
             }
         }
         map.clear();
@@ -145,37 +154,42 @@ public class CacheLoader {
         return map;
     }
 
-    public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive){
-        if(collection == null) {
-            return null;
-        }
+    public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive, boolean update){
 
         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);
+            Set<Object> alreadyVisitedEntities = new HashSet<Object>();
+            Collection<T> cachedCollection = load(collection, alreadyVisitedEntities, update);
             alreadyVisitedEntities.clear();
             logger.info("---- ending recursive load for cdm entity collection \n");
             loadedCollection = cachedCollection;
         } else {
-            loadedCollection = load(collection, null);
+            loadedCollection = load(collection, null, update);
         }
         return loadedCollection;
     }
 
     @SuppressWarnings("unchecked")
-    private <T extends Object> Collection<T> load(Collection<T> collection, Set<CdmBase> alreadyVisitedEntities){
+    private <T extends Object> Collection<T> load(Collection<T> collection, Set<Object> alreadyVisitedEntities, boolean update) {
+
+
+
+        if(collection == null || collection.isEmpty()) {
+            return collection;
+        }
         int length = collection.size();
         Object[] result = new Object[length];
         Iterator<T> collectionItr = collection.iterator();
         int count = 0;
+        // to avoid ConcurrentModificationException
+        alreadyVisitedEntities.add(collection);
         while(collectionItr.hasNext()) {
             Object obj = collectionItr.next();
             if(alreadyVisitedEntities == null) {
-                result[count] = load(obj, false);
+                result[count] = load(obj, false, update);
             } else {
-                result[count] = loadRecursive(obj, alreadyVisitedEntities);
+                result[count] = loadRecursive(obj, alreadyVisitedEntities, update);
             }
 
             count++;
@@ -199,7 +213,7 @@ public class CacheLoader {
      * @param uuid
      * @param cdmEntity
      */
-    public CdmBase load(CdmBase cdmEntity, boolean recursive) {
+    public CdmBase load(CdmBase cdmEntity, boolean recursive, boolean update) {
         if(cdmEntity == null) {
             return null;
         }
@@ -215,14 +229,14 @@ public class CacheLoader {
             if(cachedCdmEntity == cdmEntity) {
                 return cachedCdmEntity;
             }
-            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);
+            Set<Object> alreadyVisitedEntities = new HashSet<Object>();
+            CdmBase cb =  loadRecursive(cdmEntity, alreadyVisitedEntities, update);
             alreadyVisitedEntities.clear();
             logger.info("---- ending recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + "\n");
             loadedCdmBase =  cb;
@@ -237,6 +251,8 @@ public class CacheLoader {
     private CdmBase load(CdmBase cdmEntity) {
         logger.info("loading object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
 
+        cdmEntity = (CdmBase)ProxyUtils.deproxy(cdmEntity);
+
         // start by looking up the cdm entity in the cache
         CdmBase cachedCdmEntity = cdmCacher.getFromCache(cdmEntity);
 
@@ -252,10 +268,12 @@ public class CacheLoader {
         }
     }
 
-    private CdmBase loadRecursive(CdmBase cdmEntity,  Set<CdmBase> alreadyVisitedEntities) {
+    private CdmBase loadRecursive(CdmBase cdmEntity,  Set<Object> alreadyVisitedEntities, boolean update) {
 
         CdmBase cachedCdmEntity = load(cdmEntity);
-
+        if(cdmServiceCacher != null && cdmServiceCacher.exists(cachedCdmEntity)) {
+            return cachedCdmEntity;
+        }
 
         // we want to recursive through the cdmEntity (and not the cachedCdmEntity)
         // since there could be new or deleted objects in the cdmEntity sub-graph
@@ -271,12 +289,12 @@ public class CacheLoader {
                 // this object will be either a CdmBase or a Collection / Map
                 // with CdmBase as the generic type
 
-                CdmBase cdmEntityInSubGraph = getCdmBaseTypeFieldValue(cdmEntity, cachedCdmEntity, field, alreadyVisitedEntities);
+                CdmBase cdmEntityInSubGraph = getCdmBaseTypeFieldValue(cdmEntity, cachedCdmEntity, field, alreadyVisitedEntities, update);
                 if(cdmEntityInSubGraph != null) {
                     //checkForIdenticalCdmEntity(alreadyVisitedEntities, cdmEntityInSubGraph);
                     if(!alreadyVisitedEntities.contains(cdmEntityInSubGraph)) {
                         logger.info("recursive loading object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
-                        loadRecursive(cdmEntityInSubGraph, alreadyVisitedEntities);
+                        loadRecursive(cdmEntityInSubGraph, alreadyVisitedEntities, update);
                     } else {
                         logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
                     }
@@ -294,7 +312,8 @@ public class CacheLoader {
     private CdmBase getCdmBaseTypeFieldValue(CdmBase cdmEntity,
             CdmBase cachedCdmEntity,
             String fieldName,
-            Set<CdmBase> alreadyVisitedEntities) {
+            Set<Object> alreadyVisitedEntities,
+            boolean update) {
 
         // 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,
@@ -334,21 +353,21 @@ public class CacheLoader {
 
 
             CdmBase cdmEntityInSubGraph = null;
+            if(update) {
+                // 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 exception to this is found below
+                field.set(cachedCdmEntity, o);
+            }
             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 = cdmCacher.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
@@ -359,14 +378,17 @@ public class CacheLoader {
                             logger.info("setting cached + real value to '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
                             field.set(cachedCdmEntity, cachedCdmEntityInSubGraph);
                             field.set(cdmEntity, cachedCdmEntityInSubGraph);
+                        } else {
+                            // hack to stop the recursion, since the field value object in cdmEntity
+                            // is the same as the field value object in cachedCdmEntity
+                            cdmEntityInSubGraph = null;
                         }
-                        cdmEntityInSubGraph = null;
                     }
 
-                } else if(o instanceof Map) {
-                    loadRecursive((Map)o, alreadyVisitedEntities);
-                } else if(o instanceof Collection) {
-                    loadRecursive((Collection)o, alreadyVisitedEntities);
+                } else if(o instanceof Map && !alreadyVisitedEntities.contains(o)) {
+                    loadRecursive((Map)o, alreadyVisitedEntities, update);
+                } else if(o instanceof Collection && !alreadyVisitedEntities.contains(o)) {
+                    loadRecursive((Collection)o, alreadyVisitedEntities, update);
                 }
             }
             // we return the original cdm entity in the sub graph because we
@@ -398,6 +420,7 @@ public class CacheLoader {
         return false;
     }
 
+
     public static boolean isRecursiveEnabled() {
         return isRecursiveEnabled;
     }
index 321b0cc11dda808936c1fc94855857e267cb5606..7eea5c11a05a799fca3b2354c72cb881d5757812 100644 (file)
@@ -13,13 +13,13 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 
 import net.sf.ehcache.Cache;
 import net.sf.ehcache.Element;
 import net.sf.ehcache.config.CacheConfiguration;
 import net.sf.ehcache.config.SizeOfPolicyConfiguration;
 import net.sf.ehcache.statistics.LiveCacheStatistics;
-import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
 
 import org.apache.log4j.Logger;
 
@@ -59,26 +59,17 @@ public class CdmTransientEntityCacher implements ICdmCacher {
 
 
 
-    public static enum CollectionType {
-        SET,
-        LIST,
-        MAP;
-
-        @Override
-        public String toString() {
-            return this.name().toLowerCase();
-        }
-    }
-
-
     public CdmTransientEntityCacher(String cacheId, ICdmEntitySessionManager cdmEntitySessionManager) {
         this.cacheId = cacheId;
 
         cache = new Cache(getEntityCacheConfiguration(cacheId));
         CdmRemoteCacheManager.getInstance().getDefaultCacheManager().addCache(cache);
 
-        cacheLoader = new CacheLoader(this);
+
         this.cdmEntitySessionManager = cdmEntitySessionManager;
+        CdmBase fromCache = cdmServiceCacher.getFromCache(UUID.fromString("462a7819-8b00-4190-8313-88b5be81fad5"));
+
+        cacheLoader = new CacheLoader(this, cdmServiceCacher);
 
 
     }
@@ -96,18 +87,12 @@ public class CdmTransientEntityCacher implements ICdmCacher {
         SizeOfPolicyConfiguration sizeOfConfig = new SizeOfPolicyConfiguration();
         sizeOfConfig.setMaxDepth(10000);
         sizeOfConfig.setMaxDepthExceededBehavior("abort");
-        // For a better understanding on how to size caches, refer to
-        // http://ehcache.org/documentation/configuration/cache-size
-        return new CacheConfiguration(cacheId, 500)
-        .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)
-        //.eternal(true);
-        // default ttl and tti set to 2 hours
-        .timeToLiveSeconds(60*60*2)
-        .timeToIdleSeconds(60*60*2)
-        .statistics(true)
-        .sizeOfPolicy(sizeOfConfig);
-
 
+        return new CacheConfiguration(cacheId, 0)
+        .eternal(true)
+        .statistics(true)
+        .sizeOfPolicy(sizeOfConfig)
+        .overflowToOffHeap(false);
 
     }
 
@@ -129,20 +114,20 @@ public class CdmTransientEntityCacher implements ICdmCacher {
         return  CdmRemoteCacheManager.getInstance().getDefaultCacheManager().getCache(cacheId);
     }
 
-    public <T extends Object> T load(T obj, boolean recursive) {
-        return cacheLoader.load(obj, recursive);
+    public <T extends Object> T load(T obj, boolean update) {
+        return cacheLoader.load(obj, true, update);
     }
 
-    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive){
-        return cacheLoader.load(map, recursive);
+    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean update){
+        return cacheLoader.load(map, true, update);
     }
 
-    public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive){
-        return cacheLoader.load(collection, recursive);
+    public <T extends Object> Collection<T> load(Collection<T> collection, boolean update){
+        return cacheLoader.load(collection, true, update);
     }
 
-    public CdmBase load(CdmBase cdmEntity, boolean recursive) {
-        return cacheLoader.load(cdmEntity, recursive);
+    public CdmBase load(CdmBase cdmEntity, boolean update) {
+        return cacheLoader.load(cdmEntity, true, update);
     }
 
     public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
@@ -154,12 +139,13 @@ public class CdmTransientEntityCacher implements ICdmCacher {
 
     @Override
     public void put(CdmBase cdmEntity) {
-        CdmEntityCacheKey id = new CdmEntityCacheKey(cdmEntity);
-        Element cachedCdmEntityElement = cdmServiceCacher.getCacheElement(cdmEntity.getUuid());
-        if(cachedCdmEntityElement != null) {
+
+        CdmBase cachedCdmEntity = cdmServiceCacher.load(cdmEntity);
+        if(cachedCdmEntity != null) {
             logger.info("Cdm Entity with id : " + cdmEntity.getId() + " already exists in permanent cache. Ignoring put.");
             return;
         }
+        CdmEntityCacheKey id = new CdmEntityCacheKey(cdmEntity);
         getCache().put(new Element(id, cdmEntity));
     }
 
@@ -171,6 +157,7 @@ public class CdmTransientEntityCacher implements ICdmCacher {
 
     public CdmBase getFromCache(CdmEntityCacheKey id) {
         Element e = getCacheElement(id);
+
         if (e == null) {
             return null;
         } else {
@@ -192,7 +179,7 @@ public class CdmTransientEntityCacher implements ICdmCacher {
 
         if(cachedCdmEntity == null) {
             // ... then try the permanent cache
-            cachedCdmEntity = cdmServiceCacher.load(cdmBase);
+            cachedCdmEntity = cdmServiceCacher.getFromCache(cdmBase);
         }
 
         return cachedCdmEntity;
@@ -226,8 +213,7 @@ public class CdmTransientEntityCacher implements ICdmCacher {
     }
 
     public void dispose() {
-        cache.removeAll();
-        cache.flush();
+        cache.dispose();
         CdmRemoteCacheManager.getInstance().getDefaultCacheManager().removeCache(cacheId);
     }
 
@@ -243,6 +229,30 @@ public class CdmTransientEntityCacher implements ICdmCacher {
         return new CdmEntityCacheKey(entityClass, id);
     }
 
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.model.ICdmCacher#load(eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
+    public CdmBase load(CdmBase cdmEntity) {
+        return load(cdmEntity, true);
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.model.ICdmCacher#isCachable(eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
+    public boolean isCachable(CdmBase cdmEntity) {
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.model.ICdmCacher#exists(eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
+    public boolean exists(CdmBase cdmBase) {
+        return exists(generateKey(cdmBase));
+    }
+
 
 
 }
index a5e7ca6334482b235f0e7dca0f97093a4f2023c6..1b1daae0207accd8fa5c5dcf1e0db19aac897d5e 100644 (file)
@@ -19,12 +19,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import net.sf.ehcache.Cache;
+
 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.CdmCacher;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 
 /**
@@ -122,17 +125,28 @@ public class EntityCacherDebugResult {
                 CdmBase cb = (CdmBase) cei.getObject();
                 Object cbParent = cei.getParent().getObject();
 
+
+                sb.append(" - " + cei.getField().getName() + ":" + cb.getUserFriendlyTypeName() + "/" + cb.getId() +
+                        " in entity " + cbParent.getClass().getCanonicalName());
+                if(cbParent instanceof CdmBase) {
+                    sb.append(" with id : " + ((CdmBase)cbParent).getId());
+                }
+                sb.append(System.getProperty("line.separator"));
+                sb.append("  -- entity belongs to cache(s) : " + getCachesContainingEntity(cb));
+                sb.append(System.getProperty("line.separator"));
+
+
                 CdmEntityInfo dupCei = entry.getValue();
                 CdmBase dupCb = (CdmBase) dupCei.getObject();
                 Object dupCbParent = dupCei.getParent().getObject();
 
-                sb.append(" - entity : " + cb.getUserFriendlyTypeName() + "/" + cb.getId() +
-                        " as member " + cei.getField().getName() +
-                        " of entity " + cbParent.getClass().getCanonicalName());
+                sb.append(" - " + dupCei.getField().getName() + ":" + dupCb.getUserFriendlyTypeName() + "/" + dupCb.getId() +
+                        " in entity " + dupCbParent.getClass().getCanonicalName());
+                if(dupCbParent instanceof CdmBase) {
+                    sb.append(" with id : " + ((CdmBase)dupCbParent).getId());
+                }
                 sb.append(System.getProperty("line.separator"));
-                sb.append(" - duplicate entity : " + dupCb.getUserFriendlyTypeName() + "/" + dupCb.getId() +
-                        " as field " + dupCei.getField().getName() +
-                        " of entity " + dupCbParent.getClass().getCanonicalName());
+                sb.append("  -- entity belongs to cache(s) : " + getCachesContainingEntity(dupCb));
                 sb.append(System.getProperty("line.separator"));
                 sb.append("-----------");
             }
@@ -152,15 +166,36 @@ public class EntityCacherDebugResult {
 
                 sb.append(System.getProperty("line.separator"));
 
-                sb.append(" - entity : " + cb.getUserFriendlyTypeName() + "/" + cb.getId() +
-                        " as field " + cei.getField().getName() +
-                        " of entity" + cbParent.getClass().getCanonicalName());
+                sb.append(" - "  + cei.getField().getName() + ":" + cb.getUserFriendlyTypeName() + "/" + cb.getId());
+
+                if(cbParent instanceof CdmBase) {
+                    sb.append(" of entity " + ((CdmBase)cbParent).getUserFriendlyTypeName());
+                } else {
+                    sb.append(" of entity " + cbParent.getClass().getName());
+                }
             }
         }
         sb.append(System.getProperty("line.separator"));
         return sb.toString();
     }
 
+    private String getCachesContainingEntity(CdmBase cdmEntity) {
+        Cache defaultCache = CdmRemoteCacheManager.getInstance().getDefaultCacheManager().getCache(CdmCacher.DEFAULT_CACHE_NAME);
+        String caches = "";
+        Object dce = defaultCache.get(cdmEntity.getUuid());
+        if(dce != null && dce == cdmEntity) {
+            caches = CdmCacher.DEFAULT_CACHE_NAME;
+        }
+        if(!caches.isEmpty()) {
+            caches += ", ";
+        }
+        Object cte = cacher.getFromCache(CdmTransientEntityCacher.generateKey(cdmEntity));
+        if(cte != null && cte == cdmEntity) {
+            caches += cacher.toString();
+        }
+        return caches;
+    }
+
 
     private void debug(CdmBase cdmEntity, boolean recursive) {
         if(cdmEntity == null) {
@@ -368,7 +403,7 @@ public class EntityCacherDebugResult {
 
 
     private CdmEntityInfo getDuplicate(Set<CdmEntityInfo> alreadyVisitedEntities, Object objectToCompare) {
-        if(objectToCompare != null) {
+        if(objectToCompare != null ) {
             for(CdmEntityInfo cei: alreadyVisitedEntities) {
                 if(objectToCompare.equals(cei.getObject()) && objectToCompare != cei.getObject()) {
                     return cei;
@@ -440,29 +475,33 @@ public class EntityCacherDebugResult {
             if(field != null) {
                 fieldName = field.getName();
             }
+
             if(object != null) {
+                String className = object.getClass().getName();
                 if(object instanceof HibernateProxy) {
                     LazyInitializer hli = ((HibernateProxy)object).getHibernateLazyInitializer();
                     if(hli.isUninitialized()) {
-                        label = "[HibernateProxy] " + fieldName;
+                        className = "HibernateProxy";
                     } else {
-                        label = fieldName + "Object is a HibernateProxy, but initialised";
+                        className = "InitialisedHibernateProxy";
                     }
+                    label = "[" + className + "] " + fieldName;
                 } else if(object instanceof PersistentCollection) {
                     PersistentCollection pc = ((PersistentCollection)object);
                     if(!pc.wasInitialized()) {
-                        label = "[PersistentCollection] " + fieldName;
+                        className = "PersistentCollection";
                     } else {
-                        label = fieldName + "Object is a PersistentCollection, but initialised";
+                        className = "InitialisedPersistentCollection";
                     }
+                    label = "[" + className + "] " + fieldName;
                 } else if(object instanceof Collection) {
-                    String className = object.getClass().getName();
                     label = "[" + className + "] " + fieldName + " : " + String.valueOf(((Collection)object).size());
                 } else if(object instanceof Map) {
-                    String className = object.getClass().getName();
+
                     label = "[" + className + "] " + fieldName + " : " + String.valueOf(((Map)object).size());
+                } else if(object instanceof CdmBase) {
+                    label = "[" + className + ",id" + ((CdmBase)object).getId() + "] " + fieldName + " : " + object.toString();
                 } else {
-                    String className = object.getClass().getName();
                     label = "[" + className + "] " + fieldName + " : " + object.toString();
                 }
             } else {
index e61f3d4c58a0e5b9bc10f7db7d419e2a84f8f3eb..4baf85d6cda215ce8d3772e73e4b3fc135c8c0ff 100644 (file)
@@ -9,6 +9,7 @@
 */
 package eu.etaxonomy.taxeditor.remoting.cache;
 
+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -24,6 +25,9 @@ import org.hibernate.collection.internal.PersistentSet;
 import org.hibernate.collection.internal.PersistentSortedMap;
 import org.hibernate.collection.internal.PersistentSortedSet;
 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.model.common.PersistentMultiLanguageText;
 import eu.etaxonomy.taxeditor.remoting.CdmRemotingException;
@@ -35,6 +39,35 @@ import eu.etaxonomy.taxeditor.remoting.CdmRemotingException;
  */
 public class ProxyUtils {
 
+
+
+    public static enum CollectionType {
+        SET,
+        LIST,
+        MAP;
+
+        @Override
+        public String toString() {
+            return this.name().toLowerCase();
+        }
+    }
+
+    public static Object getCollectionType(Object obj) {
+        if(obj != null) {
+            if(obj instanceof List) {
+                return CollectionType.LIST;
+            }
+            if(obj instanceof Set) {
+                return CollectionType.SET;
+            }
+            if(obj instanceof Map) {
+                return CollectionType.MAP;
+            }
+            throw new CdmRemotingException("Cannot get Collection Type for " + obj.getClass().getName());
+        }
+        return null;
+    }
+
     public static Object getObject(PersistentCollection pc) {
         if(pc != null) {
             if(pc instanceof PersistentSet) {
@@ -57,4 +90,88 @@ public class ProxyUtils {
         return null;
     }
 
+    public static CollectionField getCollectionField(PersistentCollection pc) {
+        if(pc != null) {
+            if(pc instanceof PersistentSet) {
+                return new CollectionField(new HashSet((Set)pc), CollectionType.SET);
+            }
+            if(pc instanceof PersistentSortedSet) {
+                return new CollectionField(new TreeSet((Set)pc), CollectionType.SET);
+            }
+            if(pc instanceof PersistentList) {
+                return new CollectionField(new ArrayList((List)pc), CollectionType.LIST);
+            }
+            if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
+                return new CollectionField(new HashMap((Map)pc), CollectionType.MAP);
+            }
+            if(pc instanceof PersistentSortedMap) {
+                return new CollectionField(new TreeMap((Map)pc), CollectionType.MAP);
+            }
+            throw new CdmRemotingException("Cannot get Collection field for type " + pc.getClass().getName());
+        }
+        return null;
+    }
+
+    public static class CollectionField {
+        private final Object col;
+        private final CollectionType type;
+        public CollectionField(Object col, CollectionType type) {
+            this.col = col;
+            this.type = type;
+        }
+
+        public Object getCollection() {
+            return this.col;
+        }
+
+        public CollectionType getType() {
+            return this.type;
+        }
+    }
+
+
+    public static Object deproxy(Object o) {
+        if(o != null && o instanceof HibernateProxy) {
+            LazyInitializer hli = ((HibernateProxy)o).getHibernateLazyInitializer();
+            if(!hli.isUninitialized()) {
+                return ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation();
+
+            }
+        }
+
+        if(o != null && o instanceof PersistentCollection) {
+            PersistentCollection pc = ((PersistentCollection)o);
+            if(pc.wasInitialized()) {
+                return  ProxyUtils.getObject(pc);
+
+            }
+        }
+        return o;
+    }
+
+    public static void setRoleValueInOwner(Object owner, String role, Object value) {
+        if(role == null || role.isEmpty()) {
+            throw new CdmRemotingException("Role cannot be null or an empty string");
+        }
+
+        String fieldName = role.substring(role.lastIndexOf(".") + 1);
+
+        Field field = ReflectionUtils.findField(owner.getClass(), fieldName);
+
+        if(field == null) {
+            throw new CdmRemotingException("Field '" + fieldName
+                    + "' not found when searching in class '" + owner.getClass() + "' and its supercalsses");
+        }
+
+        field.setAccessible(true);
+
+        try {
+            field.set(owner, value);
+        } catch (IllegalArgumentException e) {
+            throw new CdmRemotingException(e);
+        } catch (IllegalAccessException e) {
+            throw new CdmRemotingException(e);
+        }
+    }
+
 }
index 4f2dd8799cf55af2e6bbd5107290480d56db9f5a..ddc92440a38614e01f162608af1e9c302c954a53 100644 (file)
@@ -9,29 +9,13 @@
 */
 package eu.etaxonomy.taxeditor.service;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import org.hibernate.collection.internal.PersistentList;
-import org.hibernate.collection.internal.PersistentMap;
-import org.hibernate.collection.internal.PersistentSet;
-import org.hibernate.collection.internal.PersistentSortedMap;
-import org.hibernate.collection.internal.PersistentSortedSet;
 import org.hibernate.collection.spi.PersistentCollection;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import eu.etaxonomy.cdm.api.service.ICommonService;
 import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.cdm.model.common.PersistentMultiLanguageText;
-import eu.etaxonomy.taxeditor.remoting.CdmRemotingException;
-import eu.etaxonomy.taxeditor.remoting.cache.CdmTransientEntityCacher.CollectionType;
+import eu.etaxonomy.taxeditor.remoting.cache.ProxyUtils.CollectionField;
 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
 
 /**
@@ -70,7 +54,7 @@ public class CachedCommonServiceImpl implements ICachedCommonService {
             if(cdmEntity == null) {
                 throw new NullPointerException("CDM Entity of type " + clazz.getName() + " with id " + id  + " is null.");
             }
-            return cdmEntitySessionManager.load(cdmEntity);
+            return cdmEntitySessionManager.load(cdmEntity, false);
         } else {
             return CdmBase.deproxy(commonService.find(clazz, id),clazz);
         }
@@ -81,14 +65,13 @@ public class CachedCommonServiceImpl implements ICachedCommonService {
      */
     @Override
     public PersistentCollection initializeCollection(PersistentCollection col) {
-            PersistentCollection pc = commonService.initializeCollection(col);
-            return pc;
+           return commonService.initializeCollection(col);
     }
 
     @Override
     public void updatePersistentCollection(CollectionField colf) {
        if(cacheEnabled) {
-               cdmEntitySessionManager.load(colf.getCollection());
+               cdmEntitySessionManager.load(colf.getCollection(), false);
        }
     }
 
@@ -146,46 +129,7 @@ public class CachedCommonServiceImpl implements ICachedCommonService {
         return commonService.containsValue(col, element);
     }
 
-    @SuppressWarnings("rawtypes")
-       @Override
-    public CollectionField getCollectionField(PersistentCollection pc) {
-        if(pc != null) {
-            if(pc instanceof PersistentSet) {
-                return new CollectionField(new HashSet((Set)pc), CollectionType.SET);
-            }
-            if(pc instanceof PersistentSortedSet) {
-                return new CollectionField(new TreeSet((Set)pc), CollectionType.SET);
-            }
-            if(pc instanceof PersistentList) {
-                return new CollectionField(new ArrayList((List)pc), CollectionType.LIST);
-            }
-            if(pc instanceof PersistentMap || pc instanceof PersistentMultiLanguageText) {
-                return new CollectionField(new HashMap((Map)pc), CollectionType.MAP);
-            }
-            if(pc instanceof PersistentSortedMap) {
-                return new CollectionField(new TreeMap((Map)pc), CollectionType.MAP);
-            }
-            throw new CdmRemotingException("Cannot get Collection field for type " + pc.getClass().getName());
-        }
-        return null;
-    }
 
-    public class CollectionField {
-        private final Object col;
-        private final CollectionType type;
-        public CollectionField(Object col, CollectionType type) {
-            this.col = col;
-            this.type = type;
-        }
-
-        public Object getCollection() {
-            return this.col;
-        }
-
-        public CollectionType getType() {
-            return this.type;
-        }
-    }
 
 
 
index 685d51cdb8d40c7a245df807e1009f602a5d453a..7f6d2ec9288f631281a56d5b7645a7f80eea79a9 100644 (file)
@@ -39,7 +39,11 @@ public class CdmServiceRequestExecutor extends CdmAuthenticatedHttpInvokerReques
                if(rir == null) {
                        rir = super.doExecuteRequest(config, baos);
                        if(rir.getValue() != null && !rir.hasException()) {
-                           rir = new RemoteInvocationResult(cdmEntitySessionManager.load(rir.getValue()));
+                           if(currentRemoteInvocation.getMethodName().equals("merge")) {
+                               rir = new RemoteInvocationResult(cdmEntitySessionManager.load(rir.getValue(), true));
+                           } else {
+                               rir = new RemoteInvocationResult(cdmEntitySessionManager.load(rir.getValue(), false));
+                           }
                        }
                        cache(currentRemoteInvocation, rir);
                }
index 36f6663b01eb114b93b5742d22b6fea6c70fb51b..a8095a9536d5315f00f6fdf344ac746fbd6aedd2 100644 (file)
@@ -12,7 +12,7 @@ package eu.etaxonomy.taxeditor.service;
 import org.hibernate.collection.spi.PersistentCollection;
 
 import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.taxeditor.service.CachedCommonServiceImpl.CollectionField;
+import eu.etaxonomy.taxeditor.remoting.cache.ProxyUtils.CollectionField;
 
 /**
  * @author cmathew
@@ -39,7 +39,6 @@ public interface ICachedCommonService {
 
     public boolean containsValue(PersistentCollection col, Object element);
 
-    public CollectionField getCollectionField(PersistentCollection pc);
 
 
 
index 801e3c84d54709a25176588197185b0c4fe74fd0..809cb29b63e8ad670a8292904395ba46fa1d6d9a 100644 (file)
@@ -6,40 +6,47 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.Element;
-
+import org.apache.log4j.Logger;
 import org.springframework.remoting.support.RemoteInvocation;
 import org.springframework.remoting.support.RemoteInvocationResult;
 
-import eu.etaxonomy.cdm.api.cache.CdmCacher;
+import eu.etaxonomy.cdm.api.cache.CdmServiceCacher;
 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
 import eu.etaxonomy.cdm.model.common.TermType;
 
 
 public class TermServiceRequestExecutor extends CdmServiceRequestExecutor {
+    private static final Logger logger = Logger.getLogger(TermServiceRequestExecutor.class);
 
-       private static Map<TermType, RemoteInvocationResult>  termTypeMap = new 
+       private static Map<TermType, RemoteInvocationResult>  termTypeMap = new
                        HashMap<TermType, RemoteInvocationResult>();
 
+       private static CdmServiceCacher cdmServiceCacher;
+
+       public static void setDefaultCacher(CdmServiceCacher css) {
+        cdmServiceCacher = css;
+    }
 
        @Override
        public void cache(RemoteInvocation ri, RemoteInvocationResult rir) {
-               if(ri.getMethodName().equals("listByTermType")) {
-                       if(ri.getArguments()[1] == null) {
-                               Set<DefinedTermBase> terms = new HashSet<DefinedTermBase>();
-                               if(rir.getValue() != null) {
-                                       terms.addAll((List<DefinedTermBase>)rir.getValue());
-                                       Cache defaultCache = CdmCacher.getDefaultCache();
-                                       for(DefinedTermBase<?> term : terms) {
-                                               defaultCache.put(new Element(term.getUuid(), term));
-                                       }               
-                                       termTypeMap.put((TermType)ri.getArguments()[0], rir);
-                               }
-                               
-                       }
-               }
-
+           if(cdmServiceCacher != null) {
+               if(ri.getMethodName().equals("listByTermType")) {
+                   if(ri.getArguments()[1] == null) {
+                       Set<DefinedTermBase> terms = new HashSet<DefinedTermBase>();
+                       if(rir.getValue() != null) {
+                           terms.addAll((List<DefinedTermBase>)rir.getValue());
+
+                           for(DefinedTermBase<?> term : terms) {
+                               cdmServiceCacher.put(term.getUuid(), term);
+                           }
+                           termTypeMap.put((TermType)ri.getArguments()[0], rir);
+                       }
+
+                   }
+               }
+           } else {
+               logger.info("Default CdmServiceCacher is null. Cannot cache terms");
+           }
        }
 
 
index a135b63a8e423928b1f88aecaa4388ece4a81639..6c2d959c6f0540287e25db7ef12d2db8566f800c 100644 (file)
@@ -12,6 +12,7 @@ package eu.etaxonomy.taxeditor.session;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
@@ -63,42 +64,45 @@ public class CdmEntitySession implements ICdmEntitySession  {
     }
 
 
+
     /* (non-Javadoc)
-     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(T)
+     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(java.lang.Object, boolean)
      */
     @Override
-    public  <O extends Object> O load(O obj) {
-        return cdmTransientEntityCacher.load(obj,true);
+    public  <O extends Object> O load(O obj, boolean update) {
+        return cdmTransientEntityCacher.load(obj, update);
     }
 
 
     /* (non-Javadoc)
-     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(T)
+     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(eu.etaxonomy.cdm.model.common.CdmBase, boolean)
      */
     @Override
-    public  <T extends CdmBase> T load(T cdmBase) {
-        return (T)cdmTransientEntityCacher.load(cdmBase,true);
+    public  <T extends CdmBase> T load(T cdmBase, boolean update) {
+        return (T)cdmTransientEntityCacher.load(cdmBase, update);
     }
 
+
     @Override
     public <T extends ICdmBase> void update(T cdmBase, Set<CdmBase> affectedObjects) {
-        load(cdmBase);
         addEvent(cdmBase, affectedObjects, EventType.UPDATE);
     }
 
+    @Override
+    public <T extends ICdmBase> void update(T cdmBase, CdmBase affectedObject) {
+        Set<CdmBase> set = new HashSet<CdmBase>();
+        set.add(affectedObject);
+        addEvent(cdmBase, set, EventType.UPDATE);
+    }
+
+
     @Override
     public <T extends ICdmBase> void delete(T cdmBase, Set<CdmBase> affectedObjects) {
-        for(CdmBase cb : affectedObjects) {
-            load(cb);
-        }
         addEvent(cdmBase, affectedObjects, EventType.DELETE);
     }
 
     @Override
     public <T extends ICdmBase> void delete(Set<T> cdmBases, Set<CdmBase> affectedObjects) {
-        for(CdmBase cb : affectedObjects) {
-            load(cb);
-        }
         addEvent(cdmBases, affectedObjects, EventType.DELETE);
     }
 
@@ -137,8 +141,8 @@ public class CdmEntitySession implements ICdmEntitySession  {
      * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(java.util.Collection)
      */
     @Override
-    public  <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList) {
-        return cdmTransientEntityCacher.load(cdmBaseList,true);
+    public  <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update) {
+        return cdmTransientEntityCacher.load(cdmBaseList, update);
     }
 
     /* (non-Javadoc)
@@ -198,6 +202,7 @@ public class CdmEntitySession implements ICdmEntitySession  {
      */
     @Override
     public void addEvent(ICdmBase cdmBase, Set<CdmBase> affectedObjects, EventType eventType) {
+        affectedObjects = (Set<CdmBase>) load(affectedObjects, true);
         CdmDataChangeEvent cdce = CdmDataChangeEvent.NewInstance((CdmBase)cdmBase, affectedObjects, eventType);
         CdmPostDataChangeObservableListener.getDefault().notifyObservers(cdce);
     }
@@ -208,11 +213,11 @@ public class CdmEntitySession implements ICdmEntitySession  {
      */
     @Override
     public  <T extends ICdmBase>  void addEvent(Collection <T> cdmBases, Set<CdmBase> affectedObjects, EventType eventType) {
+        affectedObjects = (Set<CdmBase>) load(affectedObjects, true);
         for(ICdmBase cdmBase : cdmBases) {
             CdmDataChangeEvent cdce = CdmDataChangeEvent.NewInstance((CdmBase)cdmBase, affectedObjects, eventType);
             CdmPostDataChangeObservableListener.getDefault().notifyObservers(cdce);
         }
-
     }
 
     /* (non-Javadoc)
@@ -230,7 +235,7 @@ public class CdmEntitySession implements ICdmEntitySession  {
     @Override
     public  <T extends CdmBase>  T remoteLoad(IService<T> service, UUID uuid) {
         T cdmBase = service.load(uuid);
-        return load(cdmBase);
+        return load(cdmBase, false);
     }
 
 
@@ -240,7 +245,7 @@ public class CdmEntitySession implements ICdmEntitySession  {
     @Override
     public <T extends CdmBase>  T remoteLoad(IService<T> service, UUID uuid, List<String> propertyPaths) {
         T cdmBase = service.load(uuid, propertyPaths);
-        return load(cdmBase);
+        return load(cdmBase, false);
     }
 
 
@@ -250,7 +255,7 @@ public class CdmEntitySession implements ICdmEntitySession  {
     @Override
     public <T extends CdmBase> UUID remoteSave(IService<T> service, T cdmBase) {
         UUID uuid = service.save(cdmBase);
-        load(cdmBase);
+        load(cdmBase,false);
         return uuid;
     }
 
@@ -260,13 +265,7 @@ public class CdmEntitySession implements ICdmEntitySession  {
      */
     @Override
     public <T extends CdmBase> T remoteUpdate(IService<T> service, T cdmBase) {
-        //debug(cdmBase);
         T mergedCdmBase = service.merge(cdmBase);
-        //cdmTransientEntityCacher.clear();
-        // FIXME:Remoting not really sure if we need to reload the new
-        // merged object or can we keep using the old one
-        //return load(mergedCdmBase);
-
         return mergedCdmBase;
     }
 
@@ -314,4 +313,5 @@ public class CdmEntitySession implements ICdmEntitySession  {
 
 
 
+
 }
index 62f44f22a526898eb48d474711b2ea6cc7cf55c0..a55c1badf2ac116954c872e992370f284c7bdab2 100644 (file)
@@ -91,11 +91,11 @@ public class CdmEntitySessionManager implements ICdmEntitySessionManager {
         * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager#load(T)
         */
        @Override
-       public <T extends Object> T load(T obj) {
+       public <T extends Object> T load(T obj, boolean update) {
                if(activeSession == null) {
                        return obj;
                } else {
-                       return activeSession.load(obj);
+                       return activeSession.load(obj, update);
                }
        }
 
@@ -104,23 +104,24 @@ public class CdmEntitySessionManager implements ICdmEntitySessionManager {
         * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager#load(T)
         */
        @Override
-       public <T extends CdmBase> T load(T cdmBase) {
+       public <T extends CdmBase> T load(T cdmBase, boolean update) {
                if(activeSession == null) {
                        return cdmBase;
                }
-               return activeSession.load(cdmBase);
+               return activeSession.load(cdmBase, update);
        }
 
 
+
        /* (non-Javadoc)
         * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager#load(java.util.Collection)
         */
        @Override
-       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList) {
+       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update) {
                if(activeSession == null) {
                        return cdmBaseList;
                }
-               return activeSession.load(cdmBaseList);
+               return activeSession.load(cdmBaseList, update);
        }
 
 
@@ -171,4 +172,6 @@ public class CdmEntitySessionManager implements ICdmEntitySessionManager {
 
 
 
+
+
 }
index 5a9a7a89d7860f4e638f0e0a1a5ca8ab3ae8452a..5fdf22b3572e73742fe1b5f221daec61de00a0b2 100644 (file)
@@ -18,9 +18,9 @@ public interface ICdmEntitySession {
 
     public LiveCacheStatistics getCacheStatistics();
 
-       public  <O extends Object> O load(O obj);
+       public  <O extends Object> O load(O obj, boolean update);
 
-       public  <T extends CdmBase> T load(T cdmBase);
+       public  <T extends CdmBase> T load(T cdmBase, boolean update);
 
        public <T extends CdmBase> EntityCacherDebugResult debug(T cdmBase);
 
@@ -28,7 +28,7 @@ public interface ICdmEntitySession {
 
        public <T extends CdmBase> EntityCacherDebugResult debug();
 
-       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList);
+       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update);
 
        public  void setEntitiesAsLatest();
 
@@ -82,6 +82,12 @@ public interface ICdmEntitySession {
 
     public boolean isActive();
 
+    /**
+     * @param cdmBase
+     * @param affectedObject
+     */
+    public <T extends ICdmBase> void update(T cdmBase, CdmBase affectedObject);
+
 
 
 
index 94e53ab62d270a037c976f1499ebd609a3abcd49..e82af5ee7709895f43223f4454291229aedc23b2 100644 (file)
@@ -10,22 +10,15 @@ public interface ICdmEntitySessionManager {
 
        public abstract void bind(ICdmEntitySessionEnabled sessionOwner);
 
-//     public abstract <T extends Object> T load(
-//                     ISessionEventListener sessionOwner, T obj);
 
-       public abstract <T extends Object> T load(T obj);
+       public abstract <T extends Object> T load(T obj, boolean update);
 
-//     public abstract <T extends CdmBase> T load(
-//                     ISessionEventListener sessionOwner, T cdmBase);
 
-       public abstract <T extends CdmBase> T load(T cdmBase);
+       public abstract <T extends CdmBase> T load(T cdmBase, boolean update);
 
-//     public abstract <T extends CdmBase> Collection<T> load(
-//                     ISessionEventListener sessionOwner, Collection<T> cdmBaseList);
 
-       public abstract <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList);
+       public abstract <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update);
 
-       //public abstract void dispose(ICdmEntitySessionEnabled owner);
 
     /**
      * @return
index 559dc5561a3c47c6bdad2c2272b25336e25e9fac..5a18a3a02a964eabd234fe1496c06ccfcdf00aa4 100644 (file)
@@ -34,7 +34,7 @@ public class MockCdmEntitySession implements ICdmEntitySession  {
      * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(java.lang.Object)
      */
     @Override
-    public <O extends Object> O load(O obj) {
+    public <O extends Object> O load(O obj, boolean update) {
         return obj;
     }
 
@@ -42,7 +42,7 @@ public class MockCdmEntitySession implements ICdmEntitySession  {
      * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(eu.etaxonomy.cdm.model.common.CdmBase)
      */
     @Override
-    public  <T extends CdmBase> T load(T cdmBase) {
+    public  <T extends CdmBase> T load(T cdmBase, boolean update) {
         return cdmBase;
     }
 
@@ -50,7 +50,7 @@ public class MockCdmEntitySession implements ICdmEntitySession  {
      * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#load(java.util.Collection)
      */
     @Override
-    public  <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList) {
+    public  <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update) {
         return cdmBaseList;
     }
 
@@ -245,4 +245,13 @@ public class MockCdmEntitySession implements ICdmEntitySession  {
         return null;
     }
 
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.session.ICdmEntitySession#update(eu.etaxonomy.cdm.model.common.ICdmBase, eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
+    public <T extends ICdmBase> void update(T cdmBase, CdmBase affectedObject) {
+
+    }
+
+
 }
index 7ff48a2d4245b4c26519608f8cbfcbf47efae5c6..beaf661dbbf6c54c19fb9a2c60aa017faebcf20f 100644 (file)
@@ -17,18 +17,18 @@ public class MockCdmEntitySessionManager implements ICdmEntitySessionManager {
        }
 
        @Override
-       public <T> T load(T obj) {
+       public <T> T load(T obj, boolean update) {
                return obj;
        }
 
        @Override
-       public <T extends CdmBase> T load(T obj) {
+       public <T extends CdmBase> T load(T obj, boolean update) {
                return obj;
        }
 
 
        @Override
-       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList) {
+       public <T extends CdmBase> Collection<T> load(Collection<T> cdmBaseList, boolean update) {
                return cdmBaseList;
        }
 
@@ -73,4 +73,5 @@ public class MockCdmEntitySessionManager implements ICdmEntitySessionManager {
         return false;
     }
 
+
 }
index 5d81225f4e4c392c3cc2f29815c2b64d2ed3e6a7..7f2110d38fa0ab8cebc2ec6a6c1e27eefadb9751 100644 (file)
@@ -61,8 +61,8 @@ import org.jboss.logging.Logger;
 
 import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteConfiguration;
 import eu.etaxonomy.taxeditor.remoting.CdmEagerLoadingException;
+import eu.etaxonomy.taxeditor.remoting.cache.ProxyUtils;
 import eu.etaxonomy.taxeditor.service.ICachedCommonService;
-import eu.etaxonomy.taxeditor.service.CachedCommonServiceImpl.CollectionField;
 
 /**
  * Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
@@ -592,26 +592,25 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
         * @throws LazyInitializationException if we cannot initialize
         */
        protected final void initialize(final boolean writing) {
-               // In remoting we are sure that session is null
-               // both when using property paths and switching off conversations
-               if(session == null && remoting) {
-                       remoteInitialize();
-               }
-
-               if ( initialized ) {
-                       return;
-               }
-
-
-               withTemporarySessionIfNeeded(
-                               new LazyInitializationWork<Object>() {
-                                       @Override
-                                       public Object doWork() {
-                                               session.initializeCollection( AbstractPersistentCollection.this, writing );
-                                               return null;
-                                       }
-                               }
-               );
+           if ( initialized ) {
+               return;
+           }
+
+           // In remoting we are sure that session is null
+           // both when using property paths and switching off conversations
+           if(session == null && remoting) {
+               remoteInitialize();
+           } else {
+               withTemporarySessionIfNeeded(
+                       new LazyInitializationWork<Object>() {
+                           @Override
+                           public Object doWork() {
+                               session.initializeCollection( AbstractPersistentCollection.this, writing );
+                               return null;
+                           }
+                       }
+                       );
+           }
        }
 
        private void throwLazyInitializationExceptionIfNotConnected() {
@@ -1307,16 +1306,19 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
                                        throw new HibernateException("commonService not initialized (null)");
                                }
 
-                               PersistentCollection col = cachedCommonService.initializeCollection(this);
+                               Object obj = ProxyUtils.deproxy(cachedCommonService.initializeCollection(this));
                                afterInitialize();
 
                                Class<?> clazz = getClass();
                                if (clazz != null) {
-                                       CollectionField cf = cachedCommonService.getCollectionField(col);
-                                       cachedCommonService.updatePersistentCollection(cf);
-                                       Field field = clazz.getDeclaredField(cf.getType().toString());
+                                       //CollectionField cf = cachedCommonService.getCollectionField(col);
+                                       //cachedCommonService.updatePersistentCollection(cf);
+                                   Object collectionType = ProxyUtils.getCollectionType(obj);
+                                       Field field = clazz.getDeclaredField(collectionType.toString());
                                        field.setAccessible(true);
-                                       field.set(this, cf.getCollection());
+                                       field.set(this, obj);
+                                       ProxyUtils.setRoleValueInOwner(owner, role, obj);
+
                                }
                        } catch (Exception ex) {
                                throw new CdmEagerLoadingException(ex);