Project

General

Profile

« Previous | Next » 

Revision 56a14252

Added by Cherian Mathew about 9 years ago

OpenInspectSessionsHandler : handler for opening the inspect session dialog
CacheLoader : moved recursive logic from cdm transient cacher to new class
CdmServiceCacher : now uses CacheLoader to recursively load entities
CdmTransientEntityCacher : moved recursive logic from cdm transient cacher to new class and corrected caching issues
EntityCacherDebugResult : corrected recursion and added getter method for debug output
CdmEntitySessionManager : now sets active session to null when it is disposed
remotingApplicationContext.xml : corrected exclude
AbstractUtility : new utility method to execute handler
InspectSessionsDialog : added debug text info and cosmetic changes
SessionsViewPart : now opens inspect sessions dialog on button push

View differences:

.gitattributes
333 333
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/api/cache/CdmServiceCacher.java -text
334 334
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/CdmEagerLoadingException.java -text
335 335
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/CdmRemotingException.java -text
336
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CacheLoader.java -text
336 337
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CachedCommonServiceImpl.java -text
337 338
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CdmClientCacheException.java -text
338 339
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CdmEntityCacheKey.java -text
......
1278 1279
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/SelectFeatureTreeWizard.java -text
1279 1280
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/SelectFeatureTreeWizardPage.java -text
1280 1281
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/OpenDistributionEditorWizardHandler.java -text
1282
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/OpenInspectSessionsHandler.java -text
1281 1283
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/OpenPasswordWizzardHandler.java -text
1282 1284
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/ShowLoginWindowHandler.java -text
1283 1285
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/ShowRemotingLoginWindowHandler.java -text
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/cdm/api/cache/CdmServiceCacher.java
7 7

  
8 8
import eu.etaxonomy.cdm.api.service.ITermService;
9 9
import eu.etaxonomy.cdm.model.common.CdmBase;
10
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
11
import eu.etaxonomy.taxeditor.remoting.cache.CacheLoader;
10 12
import eu.etaxonomy.taxeditor.remoting.cache.CdmTransientEntityCacher;
11 13

  
12 14
/**
......
21 23
 * @param <T>
22 24
 */
23 25
@Component
24
public class CdmServiceCacher extends CdmCacher {
26
public class CdmServiceCacher extends CdmCacher{
25 27

  
26 28
	@Autowired
27 29
	ITermService termService;
28 30

  
31
	private CacheLoader cacheLoader;
32

  
29 33
	@Override
30 34
	protected void setup() {
35
	    DefinedTermBase.setCacher(this);
31 36
		CdmTransientEntityCacher.setDefaultCacher(this);
37
		cacheLoader = new CacheLoader(this);
32 38
	}
33 39

  
34 40
	@Override
35 41
	protected CdmBase findByUuid(UUID uuid) {
36 42
		CdmBase term = termService.findWithoutFlush(uuid);
37
		return term;
43
		return cacheLoader.load(term, true);
44

  
38 45
	}
39 46

  
47

  
40 48
}
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CacheLoader.java
1
// $Id$
2
/**
3
 * Copyright (C) 2015 EDIT
4
 * European Distributed Institute of Taxonomy
5
 * http://www.e-taxonomy.eu
6
 *
7
 * The contents of this file are subject to the Mozilla Public License Version 1.1
8
 * See LICENSE.TXT at the top of this package for the full license terms.
9
 */
10
package eu.etaxonomy.taxeditor.remoting.cache;
11

  
12
import java.lang.reflect.Field;
13
import java.util.Collection;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19

  
20
import javassist.util.proxy.ProxyFactory;
21
import net.sf.ehcache.Cache;
22
import net.sf.ehcache.Element;
23

  
24
import org.apache.log4j.Logger;
25
import org.hibernate.collection.spi.PersistentCollection;
26
import org.hibernate.proxy.HibernateProxy;
27
import org.hibernate.proxy.LazyInitializer;
28
import org.springframework.util.ReflectionUtils;
29

  
30
import eu.etaxonomy.cdm.model.ICdmCacher;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32

  
33
/**
34
 * @author cmathew
35
 * @date 19 Feb 2015
36
 *
37
 */
38
public class CacheLoader {
39
    private static final Logger logger = Logger.getLogger(CacheLoader.class);
40

  
41
    private static boolean isRecursiveEnabled = true;
42

  
43
    private final ICdmCacher cdmCacher;
44

  
45
    private final Cache cdmlibModelCache;
46

  
47

  
48
    public CacheLoader(ICdmCacher cdmCacher) {
49
        this.cdmCacher = cdmCacher;
50
        this.cdmlibModelCache = CdmRemoteCacheManager.getInstance().getCdmModelGetMethodsCache();
51
    }
52

  
53

  
54
    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
55
        Element e = cdmlibModelCache.get(className);
56
        if (e == null) {
57
            return null;
58
        } else {
59
            return (CdmModelFieldPropertyFromClass) e.getObjectValue();
60
        }
61
    }
62

  
63
    @SuppressWarnings("unchecked")
64
    public <T extends Object> T load(T obj, boolean recursive) {
65
        if(obj == null) {
66
            return null;
67
        }
68
        if(obj instanceof CdmBase) {
69
            return (T) load((CdmBase)obj, recursive);
70
        } else if (obj instanceof Map) {
71
            return (T) load((Map<T,T>)obj, recursive);
72
        } else if (obj instanceof Collection) {
73
            return (T) load((Collection<T>)obj, recursive);
74
        }
75

  
76
        return obj;
77
    }
78

  
79
    @SuppressWarnings("unchecked")
80
    private <T extends Object> T loadRecursive(T obj, Set<CdmBase> alreadyVisitedEntities) {
81
        if(obj == null) {
82
            return null;
83
        }
84
        if(obj instanceof CdmBase) {
85
            return (T) loadRecursive((CdmBase)obj, alreadyVisitedEntities);
86
        } else if (obj instanceof Map) {
87
            return (T) load((Map<T,T>)obj, alreadyVisitedEntities);
88
        } else if (obj instanceof Collection) {
89
            return (T) load((Collection<T>)obj, alreadyVisitedEntities);
90
        }
91

  
92

  
93
        logger.info("No caching yet for type " + obj.getClass().getName());
94

  
95
        return obj;
96
    }
97

  
98
    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive){
99
        if(map == null) {
100
            return null;
101
        }
102

  
103
        if(isRecursiveEnabled && recursive) {
104
            logger.info("---- starting recursive load for cdm entity map");
105
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
106
            Map<T,T> cachedMap = load(map, alreadyVisitedEntities);
107
            alreadyVisitedEntities.clear();
108
            logger.info("---- ending recursive load for cdm entity map \n");
109
            return cachedMap;
110
        } else {
111
            return load(map, null);
112
        }
113
    }
114

  
115

  
116
    private <T extends Object> Map<T,T> load(Map<T,T> map, Set<CdmBase> alreadyVisitedEntities){
117
        if(map == null || map.isEmpty()) {
118
            return map;
119
        }
120

  
121
        int originalMapSize = map.size();
122
        Object[] result = new Object[ map.size() * 2 ];
123
        Iterator<Map.Entry<T,T>> iter = map.entrySet().iterator();
124
        int i=0;
125
        while ( iter.hasNext() ) {
126
            Map.Entry<T,T> e = iter.next();
127
            result[i++] = e.getKey();
128
            result[i++] = e.getValue();
129
        }
130

  
131
        for(i=0; i<result.length;i++) {
132
            if(alreadyVisitedEntities == null) {
133
                result[i] = load(result[i], false);
134
            } else {
135
                result[i] = loadRecursive(result[i], alreadyVisitedEntities);
136
            }
137
        }
138
        map.clear();
139
        for(i = 0; i < originalMapSize; i+=2 ) {
140
            map.put(
141
                    (T)result[i],
142
                    (T)result[i+1]
143
                    );
144
        }
145
        return map;
146
    }
147

  
148
    public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive){
149
        if(collection == null) {
150
            return null;
151
        }
152

  
153
        Collection<T> loadedCollection;
154
        if(isRecursiveEnabled && recursive) {
155
            logger.info("---- starting recursive load for cdm entity collection");
156
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
157
            Collection<T> cachedCollection = load(collection, alreadyVisitedEntities);
158
            alreadyVisitedEntities.clear();
159
            logger.info("---- ending recursive load for cdm entity collection \n");
160
            loadedCollection = cachedCollection;
161
        } else {
162
            loadedCollection = load(collection, null);
163
        }
164
        return loadedCollection;
165
    }
166

  
167
    @SuppressWarnings("unchecked")
168
    private <T extends Object> Collection<T> load(Collection<T> collection, Set<CdmBase> alreadyVisitedEntities){
169
        int length = collection.size();
170
        Object[] result = new Object[length];
171
        Iterator<T> collectionItr = collection.iterator();
172
        int count = 0;
173
        while(collectionItr.hasNext()) {
174
            Object obj = collectionItr.next();
175
            if(alreadyVisitedEntities == null) {
176
                result[count] = load(obj, false);
177
            } else {
178
                result[count] = loadRecursive(obj, alreadyVisitedEntities);
179
            }
180

  
181
            count++;
182
        }
183

  
184
        collection.clear();
185

  
186
        for ( int i = 0; i < length; i++ ) {
187
            collection.add((T)result[i]);
188
        }
189

  
190
        return collection;
191
    }
192

  
193

  
194
    /**
195
     * Puts the (Key,Value) pair of ({@link java.util.UUID}, {@link eu.etaxonomy.cdm.model.common.CdmBase}),
196
     * in the cache corresponding to the given cache id
197
     *
198
     * @param cacheId
199
     * @param uuid
200
     * @param cdmEntity
201
     */
202
    public CdmBase load(CdmBase cdmEntity, boolean recursive) {
203
        if(cdmEntity == null) {
204
            return null;
205
        }
206

  
207

  
208
        // start by looking up the cdm entity in the cache
209
        CdmBase cachedCdmEntity = cdmCacher.getFromCache(cdmEntity);
210

  
211
        if(cachedCdmEntity != null) {
212
            // if cdm entity was found in cache then
213
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
214
            // .. return if the cached and input objects are identical, else (this is a newly loaded object so) continue
215
            if(cachedCdmEntity == cdmEntity) {
216
                return cachedCdmEntity;
217
            }
218
            return cachedCdmEntity;
219
        }
220

  
221
        CdmBase loadedCdmBase;
222
        if(isRecursiveEnabled && recursive) {
223
            logger.info("---- starting recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
224
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
225
            CdmBase cb =  loadRecursive(cdmEntity, alreadyVisitedEntities);
226
            alreadyVisitedEntities.clear();
227
            logger.info("---- ending recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + "\n");
228
            loadedCdmBase =  cb;
229
        } else {
230
            loadedCdmBase = load(cdmEntity);
231
        }
232
        return loadedCdmBase;
233

  
234
    }
235

  
236

  
237
    private CdmBase load(CdmBase cdmEntity) {
238
        logger.info("loading object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
239

  
240
        // start by looking up the cdm entity in the cache
241
        CdmBase cachedCdmEntity = cdmCacher.getFromCache(cdmEntity);
242

  
243
        if(cachedCdmEntity != null) {
244
            // if cdm entity was found in cache then return ...
245
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
246
            return cachedCdmEntity;
247
        } else {
248
            // ... else save the entity in the cache
249
            cdmCacher.put(cdmEntity);
250
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " put in cache");
251
            return cdmEntity;
252
        }
253
    }
254

  
255
    private CdmBase loadRecursive(CdmBase cdmEntity,  Set<CdmBase> alreadyVisitedEntities) {
256

  
257
        CdmBase cachedCdmEntity = load(cdmEntity);
258

  
259

  
260
        // we want to recursive through the cdmEntity (and not the cachedCdmEntity)
261
        // since there could be new or deleted objects in the cdmEntity sub-graph
262

  
263
        // start by getting the fields from the cdm entity
264
        String className = cdmEntity.getClass().getName();
265
        CdmModelFieldPropertyFromClass cmgmfc = getFromCdmlibModelCache(className);
266
        if(cmgmfc != null) {
267
            alreadyVisitedEntities.add(cdmEntity);
268
            List<String> fields = cmgmfc.getFields();
269
            for(String field : fields) {
270
                // retrieve the actual object corresponding to the field.
271
                // this object will be either a CdmBase or a Collection / Map
272
                // with CdmBase as the generic type
273

  
274
                CdmBase cdmEntityInSubGraph = getCdmBaseTypeFieldValue(cdmEntity, cachedCdmEntity, field, alreadyVisitedEntities);
275
                if(cdmEntityInSubGraph != null) {
276
                    //checkForIdenticalCdmEntity(alreadyVisitedEntities, cdmEntityInSubGraph);
277
                    if(!alreadyVisitedEntities.contains(cdmEntityInSubGraph)) {
278
                        logger.info("recursive loading object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
279
                        loadRecursive(cdmEntityInSubGraph, alreadyVisitedEntities);
280
                    } else {
281
                        logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
282
                    }
283

  
284
                }
285
            }
286
        } else {
287
            throw new CdmClientCacheException("CdmEntity with class " + cdmEntity.getClass().getName() + " is not found in the cdmlib model cache. " +
288
                    "The cache may be corrupted or not in sync with the latest model version" );
289
        }
290
        return cachedCdmEntity;
291
    }
292

  
293

  
294
    private CdmBase getCdmBaseTypeFieldValue(CdmBase cdmEntity,
295
            CdmBase cachedCdmEntity,
296
            String fieldName,
297
            Set<CdmBase> alreadyVisitedEntities) {
298

  
299
        // this method attempts to make sure that for any two objects found in
300
        // the object graph, if they are equal then they should also be the same,
301
        // which is crucial for the merge to work
302
        if(cachedCdmEntity == null) {
303
            throw new CdmClientCacheException("When trying to set field value, the cached cdm entity cannot be null");
304
        }
305

  
306
        Class<?> clazz = cdmEntity.getClass();
307
        try {
308
            // this call will search in the provided class as well as
309
            // the super classes until it finds the field
310
            Field field = ReflectionUtils.findField(clazz, fieldName);
311

  
312
            if(field == null) {
313
                throw new CdmClientCacheException("Field '" + fieldName
314
                        + "' not found when searching in class '" + clazz.getName() + "' and its supercalsses");
315
            }
316
            field.setAccessible(true);
317
            Object o = field.get(cdmEntity);
318

  
319
            if(o != null && o instanceof HibernateProxy) {
320
                LazyInitializer hli = ((HibernateProxy)o).getHibernateLazyInitializer();
321
                if(!hli.isUninitialized()) {
322
                    o = ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation();
323
                    field.set(cdmEntity, o);
324
                }
325
            }
326

  
327
            if(o != null && o instanceof PersistentCollection) {
328
                PersistentCollection pc = ((PersistentCollection)o);
329
                if(pc.wasInitialized()) {
330
                    o = ProxyUtils.getObject(pc);
331
                    field.set(cdmEntity, o);
332
                }
333
            }
334

  
335

  
336
            CdmBase cdmEntityInSubGraph = null;
337
            if(o != null
338
                    && !ProxyFactory.isProxyClass(o.getClass())
339
                    && !(o instanceof PersistentCollection) ) {
340

  
341
                if(CdmBase.class.isAssignableFrom(o.getClass())) {
342
                    logger.info("found initialised cdm entity '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
343
                    cdmEntityInSubGraph  = (CdmBase)o;
344

  
345

  
346
                    CdmBase cachedCdmEntityInSubGraph = cdmCacher.getFromCache(cdmEntityInSubGraph);
347
                    // making sure that the field in cached cdm entity is always
348
                    // up-to-date by setting to the value of the cdm entity being loaded
349
                    // the only execption to this is found below
350
                    field.set(cachedCdmEntity, o);
351

  
352

  
353
                    // the only exception to updating the field to the latest value
354
                    // is the case where the field has been already initialised, cached and
355
                    // is not the same as the one in the cache, in which case we set the value
356
                    // of the field to the one found in the cache
357
                    if(cachedCdmEntityInSubGraph != null) {
358
                        if(cachedCdmEntityInSubGraph != cdmEntityInSubGraph) {
359
                            logger.info("setting cached + real value to '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
360
                            field.set(cachedCdmEntity, cachedCdmEntityInSubGraph);
361
                            field.set(cdmEntity, cachedCdmEntityInSubGraph);
362
                        }
363
                        cdmEntityInSubGraph = null;
364
                    }
365

  
366
                } else if(o instanceof Map) {
367
                    loadRecursive((Map)o, alreadyVisitedEntities);
368
                } else if(o instanceof Collection) {
369
                    loadRecursive((Collection)o, alreadyVisitedEntities);
370
                }
371
            }
372
            // we return the original cdm entity in the sub graph because we
373
            // want to continue to recurse on the input cdm entity graph
374
            // and not the one in the cache
375
            return cdmEntityInSubGraph;
376
        } catch (SecurityException e) {
377
            throw new CdmClientCacheException(e);
378
        } catch (IllegalArgumentException e) {
379
            throw new CdmClientCacheException(e);
380
        } catch (IllegalAccessException e) {
381
            throw new CdmClientCacheException(e);
382
        }
383
    }
384

  
385
    private boolean checkForIdenticalCdmEntity(Set<CdmBase> cbSet, CdmBase cbToCompare) {
386
        if(cbToCompare != null) {
387
            for(CdmBase cb : cbSet) {
388

  
389
                if(cb == cbToCompare) {
390
                    return true;
391
                } else {
392
                    if(cb.equals(cbToCompare)) {
393
                        logger.info("equal but non identical object found of type " + cbToCompare.getUserFriendlyTypeName() + " with id " + cbToCompare.getId());
394
                    }
395
                }
396
            }
397
        }
398
        return false;
399
    }
400

  
401
    public static boolean isRecursiveEnabled() {
402
        return isRecursiveEnabled;
403
    }
404

  
405
    public static void  setRecursiveEnabled(boolean ire) {
406
        isRecursiveEnabled = ire;
407
    }
408
}
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/CdmTransientEntityCacher.java
9 9
 */
10 10
package eu.etaxonomy.taxeditor.remoting.cache;
11 11

  
12
import java.lang.reflect.Field;
13 12
import java.util.ArrayList;
14 13
import java.util.Collection;
15
import java.util.HashSet;
16
import java.util.Iterator;
17 14
import java.util.List;
18 15
import java.util.Map;
19
import java.util.Set;
20 16

  
21
import javassist.util.proxy.ProxyFactory;
22 17
import net.sf.ehcache.Cache;
23 18
import net.sf.ehcache.Element;
24 19
import net.sf.ehcache.config.CacheConfiguration;
......
27 22
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
28 23

  
29 24
import org.apache.log4j.Logger;
30
import org.hibernate.collection.spi.PersistentCollection;
31
import org.hibernate.proxy.HibernateProxy;
32
import org.hibernate.proxy.LazyInitializer;
33
import org.springframework.util.ReflectionUtils;
34 25

  
35 26
import eu.etaxonomy.cdm.api.cache.CdmServiceCacher;
27
import eu.etaxonomy.cdm.model.ICdmCacher;
36 28
import eu.etaxonomy.cdm.model.common.CdmBase;
37 29
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
38 30

  
......
50 42
 *
51 43
 */
52 44

  
53
public class CdmTransientEntityCacher  {
45
public class CdmTransientEntityCacher implements ICdmCacher {
54 46

  
55 47
    private static final Logger logger = Logger.getLogger(CdmTransientEntityCacher.class);
56 48

  
57 49

  
58
    private ICdmEntitySessionManager cdmEntitySessionManager;
50
    private final ICdmEntitySessionManager cdmEntitySessionManager;
59 51

  
60 52
    private static CdmServiceCacher cdmServiceCacher;
61 53

  
62
    private String cacheId;
54
    private final String cacheId;
63 55

  
64
    private Cache cache;
56
    private final Cache cache;
57

  
58
    private final CacheLoader cacheLoader;
65 59

  
66
    private Cache cdmlibModelCache;
67 60

  
68
    private static boolean isRecursiveEnabled = true;
69 61

  
70 62
    public static enum CollectionType {
71 63
        SET,
......
78 70
        }
79 71
    }
80 72

  
81
    private CdmTransientEntityCacher() {
82

  
83
    }
84 73

  
85 74
    public CdmTransientEntityCacher(String cacheId, ICdmEntitySessionManager cdmEntitySessionManager) {
86 75
        this.cacheId = cacheId;
87 76

  
88 77
        cache = new Cache(getEntityCacheConfiguration(cacheId));
89
        cdmServiceCacher.getDefaultCacheManager().addCache(cache);
78
        CdmRemoteCacheManager.getInstance().getDefaultCacheManager().addCache(cache);
90 79

  
91
        cdmlibModelCache = CdmRemoteCacheManager.getInstance().getCdmModelGetMethodsCache();
80
        cacheLoader = new CacheLoader(this);
92 81
        this.cdmEntitySessionManager = cdmEntitySessionManager;
93 82

  
94 83

  
......
137 126
     * @return
138 127
     */
139 128
    private Cache getCache() {
140
        return cdmServiceCacher.getDefaultCacheManager().getCache(cacheId);
129
        return  CdmRemoteCacheManager.getInstance().getDefaultCacheManager().getCache(cacheId);
141 130
    }
142 131

  
143
    @SuppressWarnings("unchecked")
144 132
    public <T extends Object> T load(T obj, boolean recursive) {
145
        if(obj == null) {
146
            return null;
147
        }
148
        if(obj instanceof CdmBase) {
149
            return (T) load((CdmBase)obj, recursive);
150
        } else if (obj instanceof Map) {
151
            return (T) load((Map<T,T>)obj, recursive);
152
        } else if (obj instanceof Collection) {
153
            return (T) load((Collection<T>)obj, recursive);
154
        }
155

  
156
        return obj;
157
    }
158

  
159
    @SuppressWarnings("unchecked")
160
    private <T extends Object> T loadRecursive(T obj, Set<CdmBase> alreadyVisitedEntities) {
161
        if(obj == null) {
162
            return null;
163
        }
164
        if(obj instanceof CdmBase) {
165
            return (T) loadRecursive((CdmBase)obj, alreadyVisitedEntities);
166
        } else if (obj instanceof Map) {
167
            return (T) load((Map<T,T>)obj, alreadyVisitedEntities);
168
        } else if (obj instanceof Collection) {
169
            return (T) load((Collection<T>)obj, alreadyVisitedEntities);
170
        }
171

  
172

  
173
        logger.info("No caching yet for type " + obj.getClass().getName());
174

  
175
        return obj;
133
        return cacheLoader.load(obj, recursive);
176 134
    }
177 135

  
178 136
    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean recursive){
179
        if(map == null) {
180
            return null;
181
        }
182

  
183
        if(isRecursiveEnabled && recursive) {
184
            logger.info("---- starting recursive load for cdm entity map");
185
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
186
            Map<T,T> cachedMap = load(map, alreadyVisitedEntities);
187
            alreadyVisitedEntities.clear();
188
            logger.info("---- ending recursive load for cdm entity map \n");
189
            return cachedMap;
190
        } else {
191
            return load(map, null);
192
        }
193
    }
194

  
195

  
196
    private <T extends Object> Map<T,T> load(Map<T,T> map, Set<CdmBase> alreadyVisitedEntities){
197
        if(map == null || map.isEmpty()) {
198
            return map;
199
        }
200

  
201
        int originalMapSize = map.size();
202
        Object[] result = new Object[ map.size() * 2 ];
203
        Iterator<Map.Entry<T,T>> iter = map.entrySet().iterator();
204
        int i=0;
205
        while ( iter.hasNext() ) {
206
            Map.Entry<T,T> e = iter.next();
207
            result[i++] = e.getKey();
208
            result[i++] = e.getValue();
209
        }
210

  
211
        for(i=0; i<result.length;i++) {
212
            if(alreadyVisitedEntities == null) {
213
                result[i] = load(result[i], false);
214
            } else {
215
                result[i] = loadRecursive(result[i], alreadyVisitedEntities);
216
            }
217
        }
218
        map.clear();
219
        for(i = 0; i < originalMapSize; i+=2 ) {
220
            map.put(
221
                    (T)result[i],
222
                    (T)result[i+1]
223
                    );
224
        }
225
        return map;
137
        return cacheLoader.load(map, recursive);
226 138
    }
227 139

  
228 140
    public <T extends Object> Collection<T> load(Collection<T> collection, boolean recursive){
229
        if(collection == null) {
230
            return null;
231
        }
232

  
233
        Collection<T> loadedCollection;
234
        if(isRecursiveEnabled && recursive) {
235
            logger.info("---- starting recursive load for cdm entity collection");
236
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
237
            Collection<T> cachedCollection = load(collection, alreadyVisitedEntities);
238
            alreadyVisitedEntities.clear();
239
            logger.info("---- ending recursive load for cdm entity collection \n");
240
            loadedCollection = cachedCollection;
241
        } else {
242
            loadedCollection = load(collection, null);
243
        }
244
        return loadedCollection;
245
    }
246

  
247
    @SuppressWarnings("unchecked")
248
    private <T extends Object> Collection<T> load(Collection<T> collection, Set<CdmBase> alreadyVisitedEntities){
249
        int length = collection.size();
250
        Object[] result = new Object[length];
251
        Iterator<T> collectionItr = collection.iterator();
252
        int count = 0;
253
        while(collectionItr.hasNext()) {
254
            Object obj = collectionItr.next();
255
            if(alreadyVisitedEntities == null) {
256
                result[count] = load(obj, false);
257
            } else {
258
                result[count] = loadRecursive(obj, alreadyVisitedEntities);
259
            }
260

  
261
            count++;
262
        }
263

  
264
        collection.clear();
265

  
266
        for ( int i = 0; i < length; i++ ) {
267
            collection.add((T)result[i]);
268
        }
269

  
270
        return collection;
141
        return cacheLoader.load(collection, recursive);
271 142
    }
272 143

  
273

  
274
    /**
275
     * Puts the (Key,Value) pair of ({@link java.util.UUID}, {@link eu.etaxonomy.cdm.model.common.CdmBase}),
276
     * in the cache corresponding to the given cache id
277
     *
278
     * @param cacheId
279
     * @param uuid
280
     * @param cdmEntity
281
     */
282 144
    public CdmBase load(CdmBase cdmEntity, boolean recursive) {
283
        if(cdmEntity == null) {
284
            return null;
285
        }
286

  
287

  
288
        // start by looking up the cdm entity in the cache
289
        CdmBase cachedCdmEntity = getFromCache(cdmEntity);
290

  
291
        if(cachedCdmEntity != null) {
292
            // if cdm entity was found in cache then
293
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
294
            // .. return if the cached and input objects are identical, else (this is a newly loaded object so) continue
295
            if(cachedCdmEntity == cdmEntity) {
296
                return cachedCdmEntity;
297
            }
298
        }
299

  
300
        CdmBase loadedCdmBase;
301
        if(isRecursiveEnabled && recursive) {
302
            logger.info("---- starting recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
303
            Set<CdmBase> alreadyVisitedEntities = new HashSet<CdmBase>();
304
            CdmBase cb =  loadRecursive(cdmEntity, alreadyVisitedEntities);
305
            alreadyVisitedEntities.clear();
306
            logger.info("---- ending recursive load for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + "\n");
307
            loadedCdmBase =  cb;
308
        } else {
309
            loadedCdmBase = load(cdmEntity);
310
        }
311
        return loadedCdmBase;
312

  
313
    }
314

  
315

  
316
    private CdmBase load(CdmBase cdmEntity) {
317
        logger.info("loading object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
318

  
319
        // start by looking up the cdm entity in the cache
320
        CdmBase cachedCdmEntity = getFromCache(cdmEntity);
321

  
322
        if(cachedCdmEntity != null) {
323
            // if cdm entity was found in cache then return ...
324
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
325
            return cachedCdmEntity;
326
        } else {
327
            // ... else save the entity in the cache
328
            getCache().put(new Element(generateKey(cdmEntity), cdmEntity));
329
            logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " put in cache");
330
            return cdmEntity;
331
        }
145
        return cacheLoader.load(cdmEntity, recursive);
332 146
    }
333 147

  
334
    private CdmBase loadRecursive(CdmBase cdmEntity, Set<CdmBase> alreadyVisitedEntities) {
335

  
336
        CdmBase cachedCdmEntity = load(cdmEntity);
337

  
338
        // we want to recursive through the cdmEntity (and not the cachedCdmEntity)
339
        // since there could be new or deleted objects in the cdmEntity sub-graph
340

  
341
        // start by getting the fields from the cdm entity
342
        String className = cdmEntity.getClass().getName();
343
        CdmModelFieldPropertyFromClass cmgmfc = getFromCdmlibModelCache(className);
344
        if(cmgmfc != null) {
345
            alreadyVisitedEntities.add(cdmEntity);
346
            List<String> fields = cmgmfc.getFields();
347
            for(String field : fields) {
348
                // retrieve the actual object corresponding to the field.
349
                // this object will be either a CdmBase or a Collection / Map
350
                // with CdmBase as the generic type
351

  
352
                CdmBase cdmEntityInSubGraph = getCdmBaseTypeFieldValue(cdmEntity, cachedCdmEntity, field, alreadyVisitedEntities);
353
                if(cdmEntityInSubGraph != null) {
354
                    if(!alreadyVisitedEntities.contains(cdmEntityInSubGraph)) {
355
                        logger.info("recursive loading object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
356
                        loadRecursive(cdmEntityInSubGraph, alreadyVisitedEntities);
357
                    } else {
358
                        logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
359
                    }
360
                }
361
            }
362
        } else {
363
            throw new CdmClientCacheException("CdmEntity with class " + cdmEntity.getClass().getName() + " is not found in the cdmlib model cache. " +
364
                    "The cache may be corrupted or not in sync with the latest model version" );
365
        }
366
        return cachedCdmEntity;
148
    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
149
        return cacheLoader.getFromCdmlibModelCache(className);
367 150
    }
368 151

  
369 152

  
370
    private CdmBase getCdmBaseTypeFieldValue(CdmBase cdmEntity,
371
            CdmBase cachedCdmEntity,
372
            String fieldName,
373
            Set<CdmBase> alreadyVisitedEntities) {
374

  
375
        // this method attempts to make sure that for any two objects found in
376
        // the object graph, if they are equal then they should also be the same,
377
        // which is crucial for the merge to work
378
        if(cachedCdmEntity == null) {
379
            throw new CdmClientCacheException("When trying to set field value, the cached cdm entity cannot be null");
380
        }
381

  
382
        Class<?> clazz = cdmEntity.getClass();
383
        try {
384
            // this call will search in the provided class as well as
385
            // the super classes until it finds the field
386
            Field field = ReflectionUtils.findField(clazz, fieldName);
387

  
388
            if(field == null) {
389
                throw new CdmClientCacheException("Field '" + fieldName
390
                        + "' not found when searching in class '" + clazz.getName() + "' and its supercalsses");
391
            }
392
            field.setAccessible(true);
393
            Object o = field.get(cdmEntity);
394

  
395
            if(o != null && o instanceof HibernateProxy) {
396
                LazyInitializer hli = ((HibernateProxy)o).getHibernateLazyInitializer();
397
                if(!hli.isUninitialized()) {
398
                    o = ((HibernateProxy) o).getHibernateLazyInitializer().getImplementation();
399
                    field.set(cdmEntity, o);
400
                }
401
            }
402

  
403
            if(o != null && o instanceof PersistentCollection) {
404
                PersistentCollection pc = ((PersistentCollection)o);
405
                if(pc.wasInitialized()) {
406
                    o = ProxyUtils.getObject(pc);
407
                    field.set(cdmEntity, o);
408
                }
409
            }
410

  
411
            //field.set(cdmEntity, o);
412
            CdmBase cdmEntityInSubGraph = null;
413
            if(o != null
414
                    && !ProxyFactory.isProxyClass(o.getClass())
415
                    && !(o instanceof PersistentCollection)	) {
416

  
417
                if(CdmBase.class.isAssignableFrom(o.getClass())) {
418
                    logger.info("found initialised cdm entity '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
419
                    cdmEntityInSubGraph  = (CdmBase)o;
420
                    CdmBase cachedCdmEntityInSubGraph = getFromCache(cdmEntityInSubGraph);
421
                    // making sure that the field in cached cdm entity is always
422
                    // up-to-date by setting to the value of the cdm entity being loaded
423
                    // the only execption to this is found below
424
                    field.set(cachedCdmEntity, o);
425

  
426
                    // the only exception to updating the field to the latest value
427
                    // is the case where the field has been already initialised, cached and
428
                    // is not the same as the one in the cache, in which case we set the value
429
                    // of the field to the one found in the cache
430
                    if(cachedCdmEntityInSubGraph != null) {
431
                        if(cachedCdmEntityInSubGraph != cdmEntityInSubGraph) {
432
                            logger.info("setting cached + real value to '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
433
                            field.set(cachedCdmEntity, cachedCdmEntityInSubGraph);
434
                        }
435
                    }
436
                } else if(o instanceof Map) {
437
                    loadRecursive((Map)o, alreadyVisitedEntities);
438
                } else if(o instanceof Collection) {
439
                    loadRecursive((Collection)o, alreadyVisitedEntities);
440
                }
441
            }
442
            // we return the original cdm entity in the sub graph because we
443
            // want to continue to recurse on the input cdm entity graph
444
            // and not the one in the cache
445
            return cdmEntityInSubGraph;
446
        } catch (SecurityException e) {
447
            throw new CdmClientCacheException(e);
448
        } catch (IllegalArgumentException e) {
449
            throw new CdmClientCacheException(e);
450
        } catch (IllegalAccessException e) {
451
            throw new CdmClientCacheException(e);
452
        }
453
    }
454 153

  
455 154

  
155
    @Override
456 156
    public void put(CdmBase cdmEntity) {
457 157
        CdmEntityCacheKey id = new CdmEntityCacheKey(cdmEntity);
458
        Element cachedCdmEntityElement = getCacheElement(id);
459

  
460
        if(cachedCdmEntityElement == null) {
461
            cachedCdmEntityElement = cdmServiceCacher.getCacheElement(cdmEntity.getUuid());
462
            if(cachedCdmEntityElement != null) {
463
                logger.info("Cdm Entity with id : " + cdmEntity.getId() + " already exists in permanent cache. Ignoring put.");
464
                return;
465
            }
158
        Element cachedCdmEntityElement = cdmServiceCacher.getCacheElement(cdmEntity.getUuid());
159
        if(cachedCdmEntityElement != null) {
160
            logger.info("Cdm Entity with id : " + cdmEntity.getId() + " already exists in permanent cache. Ignoring put.");
161
            return;
466 162
        }
467

  
468 163
        getCache().put(new Element(id, cdmEntity));
469 164
    }
470 165

  
......
473 168
        return getCache().get(key);
474 169
    }
475 170

  
476
    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
477
        Element e = cdmlibModelCache.get(className);
478
        if (e == null) {
479
            return null;
480
        } else {
481
            return (CdmModelFieldPropertyFromClass) e.getObjectValue();
482
        }
483
    }
484 171

  
485 172
    public CdmBase getFromCache(CdmEntityCacheKey id) {
486 173
        Element e = getCacheElement(id);
......
496 183
        return getFromCache(cacheId);
497 184
    }
498 185

  
186
    @Override
499 187
    public CdmBase getFromCache(CdmBase cdmBase) {
500 188

  
501 189
        CdmEntityCacheKey cacheId = generateKey(cdmBase);
......
540 228
    public void dispose() {
541 229
        cache.removeAll();
542 230
        cache.flush();
543
        cdmServiceCacher.getDefaultCacheManager().removeCache(cacheId);
231
        CdmRemoteCacheManager.getInstance().getDefaultCacheManager().removeCache(cacheId);
544 232
    }
545 233

  
546 234

  
......
555 243
        return new CdmEntityCacheKey(entityClass, id);
556 244
    }
557 245

  
558
    public static boolean isRecursiveEnabled() {
559
        return isRecursiveEnabled;
560
    }
561

  
562
    public static void  setRecursiveEnabled(boolean ire) {
563
        isRecursiveEnabled = ire;
564
    }
565

  
566 246

  
567 247

  
568 248
}
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/remoting/cache/EntityCacherDebugResult.java
13 13
import java.util.ArrayList;
14 14
import java.util.Collection;
15 15
import java.util.HashMap;
16
import java.util.IdentityHashMap;
16
import java.util.HashSet;
17 17
import java.util.Iterator;
18 18
import java.util.List;
19 19
import java.util.Map;
20

  
21
import javassist.util.proxy.ProxyFactory;
20
import java.util.Set;
22 21

  
23 22
import org.apache.log4j.Logger;
24 23
import org.hibernate.collection.spi.PersistentCollection;
......
45 44

  
46 45
    private List<CdmEntityInfo> rootElements;
47 46

  
47
    StringBuilder debugOutput = new StringBuilder();
48

  
48 49
    public EntityCacherDebugResult() {
49 50
    }
50 51

  
......
52 53
    public <T extends CdmBase> EntityCacherDebugResult(CdmTransientEntityCacher cacher, List<T> rootEntities) {
53 54
        this.cacher = cacher;
54 55
        init();
56

  
55 57
        if(rootEntities != null && !rootEntities.isEmpty()) {
56 58
            for(CdmBase rootEntity : rootEntities) {
57 59
                debug(rootEntity, true);
58
                print();
60
                String out = toString(duplicateCdmEntityMap, notInCacheList, rootEntity);
61
                System.out.println(out);
62
                debugOutput.append(out);
59 63
                clear();
60 64
            }
61 65

  
......
85 89
        return rootElements;
86 90
    }
87 91

  
88
    private void print() {
89
        System.out.println(toString());
92
    private void print(Map<CdmEntityInfo, CdmEntityInfo> duplicateCdmEntityMap,
93
            List<CdmEntityInfo> notInCacheList,
94
            CdmBase rootEntity) {
95
        System.out.println(toString(duplicateCdmEntityMap, notInCacheList, rootEntity));
90 96
    }
91 97

  
92 98

  
93 99
    @Override
94 100
    public String toString() {
101
        return debugOutput.toString();
102
    }
103

  
104
    private String toString(Map<CdmEntityInfo, CdmEntityInfo> duplicateCdmEntityMap,
105
            List<CdmEntityInfo> notInCacheList,
106
            CdmBase rootEntity) {
107

  
108

  
95 109
        StringBuilder sb = new StringBuilder();
110
        sb.append(System.getProperty("line.separator"));
111
        sb.append("<<< Root Entity " + rootEntity.getUserFriendlyTypeName() + " with id " + rootEntity.getId() + " >>>");
112
        sb.append(System.getProperty("line.separator"));
96 113
        if(duplicateCdmEntityMap.isEmpty()) {
97 114
            sb.append("No Duplicate CDM Entities.");
98 115
        } else {
......
103 120
                sb.append(System.getProperty("line.separator"));
104 121
                CdmEntityInfo cei = entry.getKey();
105 122
                CdmBase cb = (CdmBase) cei.getObject();
106
                CdmBase cbParent = (CdmBase) cei.getParent().getObject();
123
                Object cbParent = cei.getParent().getObject();
107 124

  
108 125
                CdmEntityInfo dupCei = entry.getValue();
109 126
                CdmBase dupCb = (CdmBase) dupCei.getObject();
110
                CdmBase dupCbParent = (CdmBase) dupCei.getParent().getObject();
127
                Object dupCbParent = dupCei.getParent().getObject();
111 128

  
112 129
                sb.append(" - entity : " + cb.getUserFriendlyTypeName() + "/" + cb.getId() +
113
                        " as field " + cei.getField().getName() +
114
                        " of entity " + cbParent.getUserFriendlyTypeName() + "/" + cbParent.getId());
130
                        " as member " + cei.getField().getName() +
131
                        " of entity " + cbParent.getClass().getCanonicalName());
115 132
                sb.append(System.getProperty("line.separator"));
116 133
                sb.append(" - duplicate entity : " + dupCb.getUserFriendlyTypeName() + "/" + dupCb.getId() +
117 134
                        " as field " + dupCei.getField().getName() +
118
                        " of entity " + dupCbParent.getUserFriendlyTypeName() + "/" + dupCbParent.getId());
135
                        " of entity " + dupCbParent.getClass().getCanonicalName());
119 136
                sb.append(System.getProperty("line.separator"));
120 137
                sb.append("-----------");
121 138
            }
......
131 148

  
132 149
            for(CdmEntityInfo cei : notInCacheList) {
133 150
                CdmBase cb = (CdmBase) cei.getObject();
134
                CdmBase cbParent = (CdmBase) cei.getParent().getObject();
151
                Object cbParent = cei.getParent().getObject();
135 152

  
136 153
                sb.append(System.getProperty("line.separator"));
137 154

  
138 155
                sb.append(" - entity : " + cb.getUserFriendlyTypeName() + "/" + cb.getId() +
139 156
                        " as field " + cei.getField().getName() +
140
                        " of entity" + cbParent.getUserFriendlyTypeName() + "/" + cbParent.getId());
157
                        " of entity" + cbParent.getClass().getCanonicalName());
141 158
            }
142 159
        }
143

  
160
        sb.append(System.getProperty("line.separator"));
144 161
        return sb.toString();
145 162
    }
146 163

  
......
150 167
            return;
151 168
        }
152 169
        logger.info("---- starting recursive debug for cdm entity " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId());
153
        IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities = new IdentityHashMap<Object, CdmEntityInfo>();
170
        Set<CdmEntityInfo> alreadyVisitedEntities = new HashSet<CdmEntityInfo>();
154 171
        CdmEntityInfo cei = new CdmEntityInfo(cdmEntity);
155 172
        debugRecursive(cdmEntity, alreadyVisitedEntities, cei);
156 173
        rootElements.add(cei);
......
159 176
    }
160 177

  
161 178
    private <T extends Object> void debugRecursive(T obj,
162
            IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities,
179
            Set<CdmEntityInfo> alreadyVisitedEntities,
163 180
            CdmEntityInfo cei) {
164 181
        if(obj == null) {
165 182
            return;
......
167 184
        if(obj instanceof CdmBase) {
168 185
            debugRecursive((CdmBase)obj, alreadyVisitedEntities, cei);
169 186
        } else if (obj instanceof Map) {
170
           debug((Map<T,T>)obj, alreadyVisitedEntities, cei);
187
            debug((Map<T,T>)obj, alreadyVisitedEntities, cei);
171 188
        } else if (obj instanceof Collection) {
172 189
            debug((Collection<T>)obj, alreadyVisitedEntities, cei);
173 190
        }
......
178 195
    }
179 196

  
180 197
    private <T extends Object> void debug(Map<T,T> map,
181
            IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities,
198
            Set<CdmEntityInfo> alreadyVisitedEntities,
182 199
            CdmEntityInfo cei) {
183 200
        if(map == null || map.isEmpty()) {
184 201
            return;
......
198 215
    }
199 216

  
200 217
    private <T extends Object> void debug(Collection<T> collection,
201
            IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities,
218
            Set<CdmEntityInfo> alreadyVisitedEntities,
202 219
            CdmEntityInfo cei) {
203 220
        int length = collection.size();
204 221
        Object[] result = new Object[length];
......
215 232
    }
216 233

  
217 234
    private void debugRecursive(CdmBase cdmEntity,
218
            IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities,
235
            Set<CdmEntityInfo> alreadyVisitedEntities,
219 236
            CdmEntityInfo cei) {
220 237

  
238

  
221 239
        // we want to recursive through the cdmEntity (and not the cachedCdmEntity)
222 240
        // since there could be new or deleted objects in the cdmEntity sub-graph
223 241

  
......
225 243
        String className = cdmEntity.getClass().getName();
226 244
        CdmModelFieldPropertyFromClass cmgmfc = cacher.getFromCdmlibModelCache(className);
227 245
        if(cmgmfc != null) {
228
            alreadyVisitedEntities.put(cdmEntity, cei);
246
            alreadyVisitedEntities.add(cei);
229 247
            List<String> fields = cmgmfc.getFields();
230 248
            for(String field : fields) {
231 249
                // retrieve the actual object corresponding to the field.
......
233 251
                // with CdmBase as the generic type
234 252

  
235 253
                CdmEntityInfo childCei = getDebugCdmBaseTypeFieldValue(cdmEntity, field, alreadyVisitedEntities, cei);
236
                CdmBase cdmEntityInSubGraph = (CdmBase)childCei.getObject();
237
                if(cdmEntityInSubGraph != null) {
238
                    if(!alreadyVisitedEntities.keySet().contains(cdmEntityInSubGraph)) {
239
                        logger.info("recursive debugging object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
240
                        debugRecursive(cdmEntityInSubGraph, alreadyVisitedEntities, childCei);
241
                    } else {
242
                        logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
254
                if(!childCei.isProxy()) {
255
                    Object object = childCei.getObject();
256
                    if(object != null && object instanceof CdmBase) {
257
                        CdmBase cdmEntityInSubGraph = (CdmBase)object;
258
                        if(!containsIdenticalCdmEntity(alreadyVisitedEntities, cdmEntityInSubGraph)) {
259
                            logger.info("recursive debugging object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId());
260
                            debugRecursive(cdmEntityInSubGraph, alreadyVisitedEntities, childCei);
261
                        } else {
262
                            logger.info("object of type " + cdmEntityInSubGraph.getClass().getName() + " with id " + cdmEntityInSubGraph.getId() + " already visited");
263
                        }
243 264
                    }
244 265
                }
245 266
            }
......
253 274

  
254 275
    private CdmEntityInfo getDebugCdmBaseTypeFieldValue(CdmBase cdmEntity,
255 276
            String fieldName,
256
            IdentityHashMap<Object, CdmEntityInfo> alreadyVisitedEntities,
277
            Set<CdmEntityInfo> alreadyVisitedEntities,
257 278
            CdmEntityInfo cei) {
258 279

  
259 280
        CdmEntityInfo childCei = null;
......
269 290
            }
270 291
            field.setAccessible(true);
271 292
            Object o = field.get(cdmEntity);
293

  
294
            CdmBase cdmEntityInSubGraph = null;
295

  
296
            boolean isHibernateProxy = false;
297
            boolean isPersistentCollection = false;
298

  
299
            childCei = new CdmEntityInfo(o);
300
            cei.addChild(childCei);
301
            childCei.setField(field);
302

  
272 303
            if(o != null) {
304

  
273 305
                if(o instanceof HibernateProxy) {
274 306
                    LazyInitializer hli = ((HibernateProxy)o).getHibernateLazyInitializer();
275 307
                    if(!hli.isUninitialized()) {
276 308
                        o = hli.getImplementation();
309
                    } else {
310
                        isHibernateProxy = true;
277 311
                    }
278 312
                }
279 313

  
......
281 315
                    PersistentCollection pc = ((PersistentCollection)o);
282 316
                    if(pc.wasInitialized()) {
283 317
                        o = ProxyUtils.getObject(pc);
318
                    } else {
319
                        isPersistentCollection = true;
284 320
                    }
285 321
                }
286
            }
287
            childCei = new CdmEntityInfo(o);
288
            cei.addChild(childCei);
289
            childCei.setField(field);
290
            CdmBase cdmEntityInSubGraph = null;
291
            if(o != null
292
                    && !ProxyFactory.isProxyClass(o.getClass())
293
                    && !(o instanceof PersistentCollection) ) {
322
                childCei.setObject(o);
323
                childCei.setProxy(isHibernateProxy || isPersistentCollection);
324
                if(!isHibernateProxy && !isPersistentCollection) {
294 325

  
295
                if(CdmBase.class.isAssignableFrom(o.getClass())) {
296
                    logger.info("found initialised cdm entity '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
297
                    cdmEntityInSubGraph  = (CdmBase)o;
326
                    if(CdmBase.class.isAssignableFrom(o.getClass())) {
327
                        logger.info("found initialised cdm entity '" + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
328
                        cdmEntityInSubGraph  = (CdmBase)o;
298 329

  
299
                    if(alreadyVisitedEntities.keySet().contains(cdmEntityInSubGraph)) {
300 330
                        //logger.info("  - found duplicate entity at " + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
301
                        CdmEntityInfo dupCei = alreadyVisitedEntities.get(cdmEntityInSubGraph);
302
                        addDuplicateEntity(childCei, dupCei);
331
                        CdmEntityInfo dupCei = getDuplicate(alreadyVisitedEntities, cdmEntityInSubGraph);
332
                        if(dupCei != null) {
333
                            addDuplicateEntity(childCei, dupCei);
334
                        }
335

  
336
                        CdmBase cachedCdmEntityInSubGraph = cacher.getFromCache(cdmEntityInSubGraph);
337
                        // the only exception to updating the field to the latest value
338
                        // is the case where the field has been already initialised, cached and
339
                        // is not the same as the one in the cache, in which case we set the value
340
                        // of the field to the one found in the cache
341
                        if(cachedCdmEntityInSubGraph == null) {
342
                            // found a cdm entity which is not in cache - need to record this
343
                            //logger.info("  - found entity not in cache " + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
344
                            addEntityNotInCache(childCei);
345
                        }
346

  
347
                    } else if(o instanceof Map) {
348
                        debugRecursive((Map)o, alreadyVisitedEntities, childCei);
349
                    } else if(o instanceof Collection) {
350
                        debugRecursive((Collection)o, alreadyVisitedEntities, childCei);
303 351
                    }
304 352

  
305

  
306
                    CdmBase cachedCdmEntityInSubGraph = cacher.getFromCache(cdmEntityInSubGraph);
307
                    // the only exception to updating the field to the latest value
308
                    // is the case where the field has been already initialised, cached and
309
                    // is not the same as the one in the cache, in which case we set the value
310
                    // of the field to the one found in the cache
311
                    if(cachedCdmEntityInSubGraph == null) {
312
                        // found a cdm entity which is not in cache - need to record this
313
                        //logger.info("  - found entity not in cache " + fieldName + "' in object of type " + clazz.getName() + " with id " + cdmEntity.getId());
314
                        addEntityNotInCache(childCei);
315
                    }
316
                } else if(o instanceof Map) {
317
                    debugRecursive((Map)o, alreadyVisitedEntities, childCei);
318
                } else if(o instanceof Collection) {
319
                    debugRecursive((Collection)o, alreadyVisitedEntities, childCei);
320 353
                }
321 354
            }
322 355
            // we return the original cdm entity in the sub graph because we
323 356
            // want to continue to recurse on the input cdm entity graph
324 357
            // and not the one in the cache
358

  
325 359
            return childCei;
326 360
        } catch (SecurityException e) {
327 361
            throw new CdmClientCacheException(e);
......
333 367
    }
334 368

  
335 369

  
370
    private CdmEntityInfo getDuplicate(Set<CdmEntityInfo> alreadyVisitedEntities, Object objectToCompare) {
371
        if(objectToCompare != null) {
372
            for(CdmEntityInfo cei: alreadyVisitedEntities) {
373
                if(objectToCompare.equals(cei.getObject()) && objectToCompare != cei.getObject()) {
374
                    return cei;
375
                }
376
            }
377
        }
378
        return null;
379
    }
336 380

  
381
    private boolean containsIdenticalCdmEntity(Set<CdmEntityInfo> ceiSet, Object objectToCompare) {
382
        if(objectToCompare != null) {
383
            for(CdmEntityInfo cei : ceiSet) {
384
                if(cei.getObject() == objectToCompare) {
385
                    return true;
386
                }
387
            }
388
        }
389
        return false;
390
    }
337 391

  
338 392
    public class CdmEntityInfo {
339 393

  
340
        private final Object object;
394
        private Object object;
341 395
        private CdmEntityInfo parent;
342 396
        private List<CdmEntityInfo> children;
343 397
        private Field field;
344 398
        private String label;
399
        private boolean isProxy;
345 400

  
346 401
        public CdmEntityInfo(Object object) {
347 402
            this.object = object;
403
            isProxy = false;
348 404
            children = new ArrayList<CdmEntityInfo>();
349 405
        }
350 406

  
......
401 457
                    }
402 458
                } else if(object instanceof Collection) {
403 459
                    String className = object.getClass().getName();
404
                    label = "[" + className + "] " + fieldName + String.valueOf(((Collection)object).size());
460
                    label = "[" + className + "] " + fieldName + " : " + String.valueOf(((Collection)object).size());
405 461
                } else if(object instanceof Map) {
406 462
                    String className = object.getClass().getName();
407
                    label = "[" + className + "] " + fieldName + String.valueOf(((Map)object).size());
463
                    label = "[" + className + "] " + fieldName + " : " + String.valueOf(((Map)object).size());
408 464
                } else {
409 465
                    String className = object.getClass().getName();
410
                    label = "[" + className + "] " + fieldName;
466
                    label = "[" + className + "] " + fieldName + " : " + object.toString();
411 467
                }
412 468
            } else {
413 469
                label = "[NULL] " + fieldName;
......
423 479
            return object;
424 480
        }
425 481

  
482
        public void setObject(Object object) {
483
            this.object = object;
484
        }
485

  
486
        public boolean isProxy() {
487
            return isProxy;
488
        }
489

  
490
        public void setProxy(boolean isProxy) {
491
            this.isProxy = isProxy;
492
        }
493

  
426 494

  
427 495

  
428 496
    }
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/CdmEntitySession.java
260 260
     */
261 261
    @Override
262 262
    public <T extends CdmBase> T remoteUpdate(IService<T> service, T cdmBase) {
263
        debug(cdmBase);
263
        //debug(cdmBase);
264 264
        T mergedCdmBase = service.merge(cdmBase);
265 265
        //cdmTransientEntityCacher.clear();
266 266
        // FIXME:Remoting not really sure if we need to reload the new
eu.etaxonomy.taxeditor.cdmlib/src/main/java/eu/etaxonomy/taxeditor/session/CdmEntitySessionManager.java
133 133
			logger.info("No Session connected to owner, nothing to dispose");
134 134
			return;
135 135
		}
136
		if(session == activeSession) {
137
		    activeSession = null;
138
		}
136 139
		ownerSessionMap.remove(owner);
137 140
		notifyObservers();
138 141
	}
eu.etaxonomy.taxeditor.cdmlib/src/main/resources/eu/etaxonomy/cdm/remotingApplicationContext.xml
24 24
	<context:component-scan base-package="eu.etaxonomy.cdm.api.cache">
25 25
		<!-- FIXME:Remoting Temp workaround to make remoting work -->
26 26
		<context:exclude-filter type="regex"
27
			expression="eu\.etaxonomy\.cdm\.api\.cache\.CdmDaoCacher" />
27
			expression="eu\.etaxonomy\.cdm\.api\.cache\.CdmTermCacher" />
28 28
	</context:component-scan>
29 29

  
30 30
	<context:component-scan base-package="eu.etaxonomy.taxeditor.remoting.cache"/>
eu.etaxonomy.taxeditor.store/plugin.xml
696 696
            id="eu.etaxonomy.taxeditor.datasource.connect"
697 697
            name="Connect">
698 698
      </command>
699
      <command
700
            defaultHandler="eu.etaxonomy.taxeditor.handler.OpenInspectSessionsHandler"
701
            id="eu.etaxonomy.taxeditor.store.open.InspectSessionsDialog"
702
            name="Inspect Active Session">
703
      </command>
699 704
   </extension>
700 705
   <extension
701 706
         point="org.eclipse.ui.importWizards">
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/handler/OpenInspectSessionsHandler.java
1
// $Id$
2
/**
3
* Copyright (C) 2015 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.taxeditor.handler;
11

  
12
import java.util.List;
13

  
14
import org.eclipse.core.commands.AbstractHandler;
15
import org.eclipse.core.commands.ExecutionEvent;
16
import org.eclipse.core.commands.ExecutionException;
17
import org.eclipse.core.commands.IHandler;
18
import org.eclipse.swt.SWT;
19

  
20
import eu.etaxonomy.cdm.model.common.CdmBase;
21
import eu.etaxonomy.taxeditor.model.AbstractUtility;
22
import eu.etaxonomy.taxeditor.model.MessagingUtils;
23
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
24
import eu.etaxonomy.taxeditor.store.CdmStore;
25
import eu.etaxonomy.taxeditor.view.sessions.InspectSessionsDialog;
26

  
27
/**
28
 * @author cmathew
29
 * @date 18 Feb 2015
30
 *
31
 */
32
public class OpenInspectSessionsHandler extends AbstractHandler implements IHandler {
33

  
34

  
35
    /* (non-Javadoc)
36
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
37
     */
38
    /** {@inheritDoc} */
39
    @Override
40
    public Object execute(ExecutionEvent event) throws ExecutionException {
41

  
42
        Object principal = CdmStore.getCurrentAuthentiation().getPrincipal();
43

  
44
        ICdmEntitySession activeSession = CdmStore.getCurrentSessionManager().getActiveSession();
45

  
46
        if(activeSession == null) {
47
            MessagingUtils.warningDialog("No Active Session", this, "Active Session is null");
48
        } else {
49
            List<CdmBase> rootEntities = activeSession.getRootEntities();
50
            if(rootEntities == null || rootEntities.isEmpty()) {
51
                MessagingUtils.warningDialog("No Root Entities", this, "No root entities to inspect");
52
            } else {
53
                InspectSessionsDialog dialog = new InspectSessionsDialog(AbstractUtility.getShell(), SWT.NONE);
54
                dialog.open();
55
            }
56

  
57
        }
58

  
59
        return null;
60

  
61
    }
62
}
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/model/AbstractUtility.java
18 18
import java.util.TreeSet;
19 19

  
20 20
import org.eclipse.core.commands.ExecutionException;
21
import org.eclipse.core.commands.NotEnabledException;
22
import org.eclipse.core.commands.NotHandledException;
23
import org.eclipse.core.commands.common.NotDefinedException;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff