Project

General

Profile

Download (7.55 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2014 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.util.ArrayList;
13
import java.util.Collection;
14
import java.util.List;
15
import java.util.Map;
16

    
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;
23

    
24
import org.apache.log4j.Logger;
25

    
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;
30

    
31
/**
32
 *
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.
39
 *
40
 * @author cmathew
41
 * @date 14 Oct 2014
42
 *
43
 */
44

    
45
public class CdmTransientEntityCacher implements ICdmCacher {
46

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

    
49

    
50
    private final ICdmEntitySessionManager cdmEntitySessionManager;
51

    
52
    private static CdmServiceCacher cdmServiceCacher;
53

    
54
    private final String cacheId;
55

    
56
    private final Cache cache;
57

    
58
    private final CacheLoader cacheLoader;
59

    
60

    
61

    
62
    public CdmTransientEntityCacher(String cacheId, ICdmEntitySessionManager cdmEntitySessionManager) {
63
        this.cacheId = cacheId;
64

    
65
        cache = new Cache(getEntityCacheConfiguration(cacheId));
66

    
67
        CacheManager.create().addCache(cache);
68

    
69
        this.cdmEntitySessionManager = cdmEntitySessionManager;
70

    
71
        cacheLoader = new CacheLoader(this);
72
    }
73

    
74
    public CdmTransientEntityCacher(Object sessionOwner, ICdmEntitySessionManager cdmEntitySessionManager) {
75
        this(generateCacheId(sessionOwner), cdmEntitySessionManager);
76
    }
77

    
78
    public static String generateCacheId(Object sessionOwner) {
79
        return sessionOwner.getClass().getName() +  String.valueOf(sessionOwner.hashCode());
80
    }
81

    
82
    /**
83
     * Returns the default cache configuration.
84
     *
85
     * @return
86
     */
87
    private CacheConfiguration getEntityCacheConfiguration(String cacheId) {
88
        SizeOfPolicyConfiguration sizeOfConfig = new SizeOfPolicyConfiguration();
89
        sizeOfConfig.setMaxDepth(10000);
90
        sizeOfConfig.setMaxDepthExceededBehavior("abort");
91

    
92
        return new CacheConfiguration(cacheId, 0)
93
        .eternal(true)
94
        .statistics(true)
95
        .sizeOfPolicy(sizeOfConfig)
96
        .overflowToOffHeap(false);
97

    
98
    }
99

    
100
    public static void setDefaultCacher(CdmServiceCacher css) {
101
        cdmServiceCacher = css;
102
    }
103

    
104
    public LiveCacheStatistics getCacheStatistics() {
105
        return cache.getLiveCacheStatistics();
106
    }
107

    
108
    /**
109
     * Returns the cache corresponding to the cache id
110
     *
111
     * @param cacheId
112
     * @return
113
     */
114
    private Cache getCache() {
115
        return  CacheManager.create().getCache(cacheId);
116
    }
117

    
118
    public <T extends Object> T load(T obj, boolean update) {
119
        return cacheLoader.load(obj, true, update);
120
    }
121

    
122
    public <T extends Object> Map<T,T> load(Map<T,T> map, boolean update){
123
        return cacheLoader.load(map, true, update);
124
    }
125

    
126
    public <T extends Object> Collection<T> load(Collection<T> collection, boolean update){
127
        return cacheLoader.load(collection, true, update);
128
    }
129

    
130
    public CdmBase load(CdmBase cdmEntity, boolean update) {
131
        return cacheLoader.load(cdmEntity, true, update);
132
    }
133

    
134
    public CdmModelFieldPropertyFromClass getFromCdmlibModelCache(String className) {
135
        return cacheLoader.getFromCdmlibModelCache(className);
136
    }
137

    
138

    
139

    
140

    
141
    @Override
142
    public void put(CdmBase cdmEntity) {
143

    
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.");
147
            return;
148
        }
149
        CdmEntityCacheKey id = new CdmEntityCacheKey(cdmEntity);
150

    
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");
155
            return;
156
        }
157
        logger.info(" - object of type " + cdmEntity.getClass().getName() + " with id " + cdmEntity.getId() + " already exists");
158
    }
159

    
160

    
161
    private Element getCacheElement(CdmEntityCacheKey key) {
162
        return getCache().get(key);
163
    }
164

    
165

    
166
    public CdmBase getFromCache(CdmEntityCacheKey id) {
167
        Element e = getCacheElement(id);
168

    
169
        if (e == null) {
170
            return null;
171
        } else {
172
            return (CdmBase) e.getObjectValue();
173
        }
174
    }
175

    
176
    public CdmBase getFromCache(Class<? extends CdmBase> clazz, int id) {
177
        CdmEntityCacheKey cacheId = generateKey(clazz,id);
178
        return getFromCache(cacheId);
179
    }
180

    
181
    @Override
182
    public CdmBase getFromCache(CdmBase cdmBase) {
183

    
184
        CdmEntityCacheKey cacheId = generateKey(cdmBase);
185
        // first try this cache
186
        CdmBase  cachedCdmEntity = getFromCache(cacheId);
187

    
188
        if(cachedCdmEntity == null) {
189
            // ... then try the permanent cache
190
            cachedCdmEntity = cdmServiceCacher.getFromCache(cdmBase.getUuid());
191
        }
192

    
193
        return cachedCdmEntity;
194
    }
195

    
196
    public CdmBase getFromCache(CdmBase cdmBase, Class<? extends CdmBase> clazz) {
197

    
198
        cdmBase = CdmBase.deproxy(cdmBase, clazz);
199
        return getFromCache(cdmBase);
200
    }
201

    
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());
207
        }
208
        return entities;
209
    }
210

    
211
    public boolean exists(CdmEntityCacheKey key) {
212
        return (getCacheElement(key) != null);
213
    }
214

    
215
    public boolean existsAndIsNotNull(CdmEntityCacheKey id) {
216
        return getFromCache(id) != null;
217
    }
218

    
219
    public void clear() {
220
        cache.removeAll();
221
    }
222

    
223
    public void dispose() {
224
        cache.dispose();
225

    
226
    }
227

    
228

    
229
    public static CdmEntityCacheKey generateKey(Class<? extends CdmBase> clazz, int id) {
230
        return new CdmEntityCacheKey(clazz, id);
231
    }
232

    
233

    
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);
238
    }
239

    
240
    /* (non-Javadoc)
241
     * @see eu.etaxonomy.cdm.model.ICdmCacher#load(eu.etaxonomy.cdm.model.common.CdmBase)
242
     */
243
    @Override
244
    public CdmBase load(CdmBase cdmEntity) {
245
        return load(cdmEntity, true);
246
    }
247

    
248
    /* (non-Javadoc)
249
     * @see eu.etaxonomy.cdm.model.ICdmCacher#isCachable(eu.etaxonomy.cdm.model.common.CdmBase)
250
     */
251
    @Override
252
    public boolean isCachable(CdmBase cdmEntity) {
253
        return true;
254
    }
255

    
256
    /* (non-Javadoc)
257
     * @see eu.etaxonomy.cdm.model.ICdmCacher#exists(eu.etaxonomy.cdm.model.common.CdmBase)
258
     */
259
    @Override
260
    public boolean exists(CdmBase cdmBase) {
261
        return exists(generateKey(cdmBase));
262
    }
263

    
264

    
265

    
266
}
(7-7/9)