3 * Copyright (C) 2014 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.remoting
.cache
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.List
;
17 import net
.sf
.ehcache
.Cache
;
18 import net
.sf
.ehcache
.CacheManager
;
19 import net
.sf
.ehcache
.Element
;
20 import net
.sf
.ehcache
.config
.CacheConfiguration
;
21 import net
.sf
.ehcache
.config
.SizeOfPolicyConfiguration
;
22 import net
.sf
.ehcache
.statistics
.LiveCacheStatistics
;
24 import org
.apache
.log4j
.Logger
;
26 import eu
.etaxonomy
.cdm
.api
.cache
.CdmServiceCacher
;
27 import eu
.etaxonomy
.cdm
.model
.ICdmCacher
;
28 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
29 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySessionManager
;
33 * This cache guarantees that
34 * - all objects put will be ancestors of CdmBase
35 * - all CdmBase objects in the cache will be already de-proxied
36 * - after any CdmBase object is put in the cache,
37 * all non-null / non-proxy CdmBase objects in the sub-graph
38 * will also be present in the cache.
45 public class CdmTransientEntityCacher
implements ICdmCacher
{
47 private static final Logger logger
= Logger
.getLogger(CdmTransientEntityCacher
.class);
50 private final ICdmEntitySessionManager cdmEntitySessionManager
;
52 private static CdmServiceCacher cdmServiceCacher
;
54 private final String cacheId
;
56 private final Cache cache
;
58 private final CacheLoader cacheLoader
;
62 public CdmTransientEntityCacher(String cacheId
, ICdmEntitySessionManager cdmEntitySessionManager
) {
63 this.cacheId
= cacheId
;
65 cache
= new Cache(getEntityCacheConfiguration(cacheId
));
67 CacheManager
.create().addCache(cache
);
69 this.cdmEntitySessionManager
= cdmEntitySessionManager
;
71 cacheLoader
= new CacheLoader(this);
74 public CdmTransientEntityCacher(Object sessionOwner
, ICdmEntitySessionManager cdmEntitySessionManager
) {
75 this(generateCacheId(sessionOwner
), cdmEntitySessionManager
);
78 public static String
generateCacheId(Object sessionOwner
) {
79 return sessionOwner
.getClass().getName() + String
.valueOf(sessionOwner
.hashCode());
83 * Returns the default cache configuration.
87 private CacheConfiguration
getEntityCacheConfiguration(String cacheId
) {
88 SizeOfPolicyConfiguration sizeOfConfig
= new SizeOfPolicyConfiguration();
89 sizeOfConfig
.setMaxDepth(10000);
90 sizeOfConfig
.setMaxDepthExceededBehavior("abort");
92 return new CacheConfiguration(cacheId
, 0)
95 .sizeOfPolicy(sizeOfConfig
)
96 .overflowToOffHeap(false);
100 public static void setDefaultCacher(CdmServiceCacher css
) {
101 cdmServiceCacher
= css
;
104 public LiveCacheStatistics
getCacheStatistics() {
105 return cache
.getLiveCacheStatistics();
109 * Returns the cache corresponding to the cache id
114 private Cache
getCache() {
115 return CacheManager
.create().getCache(cacheId
);
118 public <T
extends Object
> T
load(T obj
, boolean update
) {
119 return cacheLoader
.load(obj
, true, update
);
122 public <T
extends Object
> Map
<T
,T
> load(Map
<T
,T
> map
, boolean update
){
123 return cacheLoader
.load(map
, true, update
);
126 public <T
extends Object
> Collection
<T
> load(Collection
<T
> collection
, boolean update
){
127 return cacheLoader
.load(collection
, true, update
);
130 public CdmBase
load(CdmBase cdmEntity
, boolean update
) {
131 return cacheLoader
.load(cdmEntity
, true, update
);
134 public CdmModelFieldPropertyFromClass
getFromCdmlibModelCache(String className
) {
135 return cacheLoader
.getFromCdmlibModelCache(className
);
142 public void put(CdmBase cdmEntity
) {
144 CdmBase cachedCdmEntity
= cdmServiceCacher
.load(cdmEntity
);
145 if(cachedCdmEntity
!= null) {
146 logger
.info("Cdm Entity with id : " + cdmEntity
.getId() + " already exists in permanent cache. Ignoring put.");
149 CdmEntityCacheKey id
= new CdmEntityCacheKey(cdmEntity
);
151 cachedCdmEntity
= getFromCache(id
);
152 if(cachedCdmEntity
== null) {
153 getCache().put(new Element(id
, cdmEntity
));
154 logger
.info(" - object of type " + cdmEntity
.getClass().getName() + " with id " + cdmEntity
.getId() + " put in cache");
157 logger
.info(" - object of type " + cdmEntity
.getClass().getName() + " with id " + cdmEntity
.getId() + " already exists");
161 private Element
getCacheElement(CdmEntityCacheKey key
) {
162 return getCache().get(key
);
166 public CdmBase
getFromCache(CdmEntityCacheKey id
) {
167 Element e
= getCacheElement(id
);
172 return (CdmBase
) e
.getObjectValue();
176 public CdmBase
getFromCache(Class
<?
extends CdmBase
> clazz
, int id
) {
177 CdmEntityCacheKey cacheId
= generateKey(clazz
,id
);
178 return getFromCache(cacheId
);
182 public CdmBase
getFromCache(CdmBase cdmBase
) {
184 CdmEntityCacheKey cacheId
= generateKey(cdmBase
);
185 // first try this cache
186 CdmBase cachedCdmEntity
= getFromCache(cacheId
);
188 if(cachedCdmEntity
== null) {
189 // ... then try the permanent cache
190 cachedCdmEntity
= cdmServiceCacher
.getFromCache(cdmBase
.getUuid());
193 return cachedCdmEntity
;
196 public CdmBase
getFromCache(CdmBase cdmBase
, Class
<?
extends CdmBase
> clazz
) {
198 cdmBase
= CdmBase
.deproxy(cdmBase
, clazz
);
199 return getFromCache(cdmBase
);
202 public List
<CdmBase
> getAllEntities() {
203 List
<CdmBase
> entities
= new ArrayList
<CdmBase
>();
204 Map
<String
, CdmBase
> elementsMap
= getCache().getAllWithLoader(getCache().getKeys(), null);
205 for (Map
.Entry
<String
, CdmBase
> entry
: elementsMap
.entrySet()) {
206 entities
.add(entry
.getValue());
211 public boolean exists(CdmEntityCacheKey key
) {
212 return (getCacheElement(key
) != null);
215 public boolean existsAndIsNotNull(CdmEntityCacheKey id
) {
216 return getFromCache(id
) != null;
219 public void clear() {
223 public void dispose() {
229 public static CdmEntityCacheKey
generateKey(Class
<?
extends CdmBase
> clazz
, int id
) {
230 return new CdmEntityCacheKey(clazz
, id
);
234 public static CdmEntityCacheKey
generateKey(CdmBase cdmBase
) {
235 Class
<?
extends CdmBase
> entityClass
= cdmBase
.getClass();
236 int id
= cdmBase
.getId();
237 return new CdmEntityCacheKey(entityClass
, id
);
241 * @see eu.etaxonomy.cdm.model.ICdmCacher#load(eu.etaxonomy.cdm.model.common.CdmBase)
244 public CdmBase
load(CdmBase cdmEntity
) {
245 return load(cdmEntity
, true);
249 * @see eu.etaxonomy.cdm.model.ICdmCacher#isCachable(eu.etaxonomy.cdm.model.common.CdmBase)
252 public boolean isCachable(CdmBase cdmEntity
) {
257 * @see eu.etaxonomy.cdm.model.ICdmCacher#exists(eu.etaxonomy.cdm.model.common.CdmBase)
260 public boolean exists(CdmBase cdmBase
) {
261 return exists(generateKey(cdmBase
));