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
.Element
;
19 import net
.sf
.ehcache
.config
.CacheConfiguration
;
20 import net
.sf
.ehcache
.config
.SizeOfPolicyConfiguration
;
21 import net
.sf
.ehcache
.statistics
.LiveCacheStatistics
;
22 import net
.sf
.ehcache
.store
.MemoryStoreEvictionPolicy
;
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 static enum CollectionType
{
68 public String
toString() {
69 return this.name().toLowerCase();
74 public CdmTransientEntityCacher(String cacheId
, ICdmEntitySessionManager cdmEntitySessionManager
) {
75 this.cacheId
= cacheId
;
77 cache
= new Cache(getEntityCacheConfiguration(cacheId
));
78 CdmRemoteCacheManager
.getInstance().getDefaultCacheManager().addCache(cache
);
80 cacheLoader
= new CacheLoader(this);
81 this.cdmEntitySessionManager
= cdmEntitySessionManager
;
86 public CdmTransientEntityCacher(Object obj
, ICdmEntitySessionManager cdmEntitySessionManager
) {
87 this(obj
.getClass().getName() + String
.valueOf(obj
.hashCode()), cdmEntitySessionManager
);
91 * Returns the default cache configuration.
95 private CacheConfiguration
getEntityCacheConfiguration(String cacheId
) {
96 SizeOfPolicyConfiguration sizeOfConfig
= new SizeOfPolicyConfiguration();
97 sizeOfConfig
.setMaxDepth(10000);
98 sizeOfConfig
.setMaxDepthExceededBehavior("abort");
99 // For a better understanding on how to size caches, refer to
100 // http://ehcache.org/documentation/configuration/cache-size
101 return new CacheConfiguration(cacheId
, 500)
102 .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy
.LFU
)
104 // default ttl and tti set to 2 hours
105 .timeToLiveSeconds(60*60*2)
106 .timeToIdleSeconds(60*60*2)
108 .sizeOfPolicy(sizeOfConfig
);
114 public static void setDefaultCacher(CdmServiceCacher css
) {
115 cdmServiceCacher
= css
;
118 public LiveCacheStatistics
getCacheStatistics() {
119 return cache
.getLiveCacheStatistics();
123 * Returns the cache corresponding to the cache id
128 private Cache
getCache() {
129 return CdmRemoteCacheManager
.getInstance().getDefaultCacheManager().getCache(cacheId
);
132 public <T
extends Object
> T
load(T obj
, boolean recursive
) {
133 return cacheLoader
.load(obj
, recursive
);
136 public <T
extends Object
> Map
<T
,T
> load(Map
<T
,T
> map
, boolean recursive
){
137 return cacheLoader
.load(map
, recursive
);
140 public <T
extends Object
> Collection
<T
> load(Collection
<T
> collection
, boolean recursive
){
141 return cacheLoader
.load(collection
, recursive
);
144 public CdmBase
load(CdmBase cdmEntity
, boolean recursive
) {
145 return cacheLoader
.load(cdmEntity
, recursive
);
148 public CdmModelFieldPropertyFromClass
getFromCdmlibModelCache(String className
) {
149 return cacheLoader
.getFromCdmlibModelCache(className
);
156 public void put(CdmBase cdmEntity
) {
157 CdmEntityCacheKey id
= new CdmEntityCacheKey(cdmEntity
);
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.");
163 getCache().put(new Element(id
, cdmEntity
));
167 private Element
getCacheElement(CdmEntityCacheKey key
) {
168 return getCache().get(key
);
172 public CdmBase
getFromCache(CdmEntityCacheKey id
) {
173 Element e
= getCacheElement(id
);
177 return (CdmBase
) e
.getObjectValue();
181 public CdmBase
getFromCache(Class
<?
extends CdmBase
> clazz
, int id
) {
182 CdmEntityCacheKey cacheId
= generateKey(clazz
,id
);
183 return getFromCache(cacheId
);
187 public CdmBase
getFromCache(CdmBase cdmBase
) {
189 CdmEntityCacheKey cacheId
= generateKey(cdmBase
);
190 // first try this cache
191 CdmBase cachedCdmEntity
= getFromCache(cacheId
);
193 if(cachedCdmEntity
== null) {
194 // ... then try the permanent cache
195 cachedCdmEntity
= cdmServiceCacher
.load(cdmBase
);
198 return cachedCdmEntity
;
201 public CdmBase
getFromCache(CdmBase cdmBase
, Class
<?
extends CdmBase
> clazz
) {
203 cdmBase
= CdmBase
.deproxy(cdmBase
, clazz
);
204 return getFromCache(cdmBase
);
207 public List
<CdmBase
> getAllEntities() {
208 List
<CdmBase
> entities
= new ArrayList
<CdmBase
>();
209 Map
<String
, CdmBase
> elementsMap
= getCache().getAllWithLoader(getCache().getKeys(), null);
210 for (Map
.Entry
<String
, CdmBase
> entry
: elementsMap
.entrySet()) {
211 entities
.add(entry
.getValue());
216 public boolean exists(CdmEntityCacheKey key
) {
217 return (getCacheElement(key
) != null);
220 public boolean existsAndIsNotNull(CdmEntityCacheKey id
) {
221 return getFromCache(id
) != null;
224 public void clear() {
228 public void dispose() {
231 CdmRemoteCacheManager
.getInstance().getDefaultCacheManager().removeCache(cacheId
);
235 public static CdmEntityCacheKey
generateKey(Class
<?
extends CdmBase
> clazz
, int id
) {
236 return new CdmEntityCacheKey(clazz
, id
);
240 public static CdmEntityCacheKey
generateKey(CdmBase cdmBase
) {
241 Class
<?
extends CdmBase
> entityClass
= cdmBase
.getClass();
242 int id
= cdmBase
.getId();
243 return new CdmEntityCacheKey(entityClass
, id
);