Project

General

Profile

Download (7.39 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.api.service;
11

    
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.concurrent.ConcurrentHashMap;
17

    
18
import org.apache.log4j.Logger;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.stereotype.Service;
21
import org.springframework.transaction.annotation.Transactional;
22

    
23
import eu.etaxonomy.cdm.model.common.CdmBase;
24
import eu.etaxonomy.cdm.model.metadata.CdmPreference;
25
import eu.etaxonomy.cdm.model.metadata.CdmPreference.PrefKey;
26
import eu.etaxonomy.cdm.model.metadata.IPreferencePredicate;
27
import eu.etaxonomy.cdm.model.metadata.PreferenceResolver;
28
import eu.etaxonomy.cdm.model.metadata.PreferenceSubject;
29
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
30
import eu.etaxonomy.cdm.persistence.dao.common.IPreferenceDao;
31

    
32
/**
33
 * Service to store and access {@link CdmPreference cdm preferences}.
34
 * On how to use cdm preferences see the documentation there.
35
 *
36
 * @author a.mueller
37
 * @since 2013-09-09
38
 */
39
@Service
40
@Transactional(readOnly = true)
41
public class PreferenceServiceImpl implements IPreferenceService {
42

    
43
    @SuppressWarnings("unused")
44
	private static final Logger logger = Logger.getLogger(PreferenceServiceImpl.class);
45

    
46
    @Autowired
47
    private IPreferenceDao dao;
48

    
49
    private Map<String, CdmPreference> cache = new ConcurrentHashMap<>();
50

    
51
    private boolean cacheIsComplete = false;
52

    
53
    private boolean cacheIsLocked = false;
54

    
55
    @Override
56
	public CdmPreference findExact(PrefKey key) {
57
		String cacheKey = cacheKey(key);
58
        return fromCacheGet(key, cacheKey);
59
	}
60

    
61
    @Override
62
    public CdmPreference find(PrefKey key) {
63
        CdmPreference pref = PreferenceResolver.resolve(list(), key);
64
        return pref;
65
    }
66

    
67
    @Override
68
    public CdmPreference findDatabase(IPreferencePredicate<?> predicate){
69
        PrefKey key = CdmPreference.NewKey(PreferenceSubject.NewDatabaseInstance(), predicate);
70
        return find(key);
71
    }
72

    
73
    @Override
74
    public CdmPreference findVaadin(IPreferencePredicate<?> predicate){
75
        PrefKey key = CdmPreference.NewKey(PreferenceSubject.NewVaadinInstance(), predicate);
76
        return find(key);
77
    }
78

    
79
    @Override
80
    public CdmPreference findTaxEditor(IPreferencePredicate<?> predicate){
81
        PrefKey key = CdmPreference.NewKey(PreferenceSubject.NewTaxEditorInstance(), predicate);
82
        return find(key);
83
    }
84

    
85
	@Override
86
    @Transactional(readOnly = false)
87
	public void set(CdmPreference preference) {
88
		dao.set(preference);
89
		cachePut(preference);
90
	}
91

    
92
    @Override
93
    @Transactional(readOnly = false)
94
    public void remove(PrefKey key) {
95
        dao.remove(key);
96
        removeFromCache(key);
97
    }
98

    
99
    @Override
100
	public long count() {
101
		return dao.count();
102
	}
103

    
104
	@Override
105
    public List<CdmPreference> list() {
106
	    if(!cacheIsComplete) {
107
	        cacheFullUpdate();
108
	    }
109
        return new ArrayList<>(cacheValues());
110
    }
111

    
112
    @Override
113
    public List<CdmPreference> list(IPreferencePredicate<?> predicate) {
114
        // using the cache for this method makes not much sense
115
        return dao.list(predicate);
116
    }
117

    
118
    @Override
119
    public CdmPreference find(TaxonNode taxonNode, String predicate) {
120

    
121
        return dao.find(taxonNode, predicate);
122
//      caching of taxon node related prefs disabled, see https://dev.e-taxonomy.eu/redmine/issues/9152#note-8
123
//      code has been left here in case we decide later for solution 2 which has been suggested also in comment 5
124
//        String cacheKey = cacheKey(taxonNode, predicate);
125
//        return fromCacheOrFind(taxonNode, predicate, cacheKey);
126
    }
127

    
128
    @Override
129
    public CdmPreference find(TaxonNode taxonNode, IPreferencePredicate<?> predicate){
130
        return find(taxonNode, predicate.getKey());
131
    }
132

    
133
// ********************** NOT YET HANDLED *******************/
134

    
135
    @Override
136
    public List<CdmPreference> list(String subject, String predicate) {
137
        //FIXME
138
        throw new RuntimeException("list(String, String) not yet implemented" );
139
    }
140

    
141
    @Override
142
    //this method is only partly implemented
143
    public CdmPreference find(CdmBase taxonNodeRelatedCdmBase, String predicate) {
144
        TaxonNode taxonNode = mapToTaxonNode(taxonNodeRelatedCdmBase);
145
        return dao.find(taxonNode, predicate);
146
    }
147

    
148
    private TaxonNode mapToTaxonNode(CdmBase taxonNodeRelatedCdmBase) {
149
        if (taxonNodeRelatedCdmBase == null){
150
            return null;
151
        }else if (taxonNodeRelatedCdmBase.isInstanceOf(TaxonNode.class)){
152
            return CdmBase.deproxy(taxonNodeRelatedCdmBase, TaxonNode.class);
153
        }else{
154
            throw new RuntimeException("mapToTaxonNode not yet implemented for " + taxonNodeRelatedCdmBase.getClass().getSimpleName());
155
        }
156
    }
157

    
158
    // ====================== Cache methods ======================= //
159

    
160
    /**
161
     * Concatenates subject and predicate as key for the cache map
162
     */
163
    private String cacheKey(PrefKey key) {
164
        return key.getSubject() + "@" + key.getPredicate();
165
    }
166

    
167
    /**
168
     * @deprecated caching of taxon node related prefs disabled, see https://dev.e-taxonomy.eu/redmine/issues/9152#note-8
169
     * code has been left here in case we decide later for solution 2 which has been suggested also in comment 5
170
     */
171
    @Deprecated
172
    private String cacheKey(TaxonNode taxonNode, String predicate) {
173
        return taxonNode.treeIndex() + predicate;
174
    }
175

    
176

    
177
    // --------------- non locking cache read methods --------------- //
178

    
179
    protected Collection<CdmPreference> cacheValues() {
180
        waitForCache();
181
        return cache.values();
182
    }
183

    
184
    protected CdmPreference fromCacheGet(PrefKey key, String cacheKey) {
185
        waitForCache();
186
        return cache.computeIfAbsent(cacheKey, k -> dao.get(key));
187
    }
188

    
189

    
190
    /**
191
     * @deprecated caching of taxon node related prefs disabled, see https://dev.e-taxonomy.eu/redmine/issues/9152#note-8
192
     * code has been left here in case we decide later for solution 2 which has been suggested also in comment 5
193
     */
194
    @Deprecated
195
    protected CdmPreference fromCacheOrFind(TaxonNode taxonNode, String predicate, String cacheKey) {
196
        waitForCache();
197
        return cache.computeIfAbsent(cacheKey, k -> dao.find(taxonNode, predicate));
198
    }
199

    
200
    // --------------- cache locking methods --------------- //
201

    
202
    protected void cachePut(CdmPreference preference) {
203
        waitForCache();
204
        cacheIsLocked = true;
205
        cache.put(cacheKey(preference.getKey()), preference);
206
        cacheIsLocked = false;
207
    }
208

    
209

    
210
    protected void removeFromCache(PrefKey key) {
211
        waitForCache();
212
        cacheIsLocked = true;
213
        cache.remove(cacheKey(key));
214
        cacheIsLocked = false;
215
    }
216

    
217
    protected void cacheFullUpdate() {
218
        waitForCache();
219
        cacheIsLocked = true;
220
        cache.clear();
221
        for(CdmPreference pref :  dao.list()){
222
            cache.put(cacheKey(pref.getKey()), pref);
223
        }
224
        cacheIsComplete = true;
225
        cacheIsLocked = false;
226
    }
227

    
228
    protected void waitForCache() {
229
        while(cacheIsLocked) {
230
            try {
231
                Thread.sleep(1);
232
            } catch (InterruptedException e) {
233
                // just keep on sleeping, we may improve this later on
234
            }
235
        }
236
    }
237

    
238
}
(77-77/97)