2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.api
.service
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.List
;
16 import java
.util
.concurrent
.ConcurrentHashMap
;
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
;
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
;
33 * Service to store and access {@link CdmPreference cdm preferences}.
34 * On how to use cdm preferences see the documentation there.
40 @Transactional(readOnly
= true)
41 public class PreferenceServiceImpl
implements IPreferenceService
{
43 @SuppressWarnings("unused")
44 private static final Logger logger
= Logger
.getLogger(PreferenceServiceImpl
.class);
47 private IPreferenceDao dao
;
49 private Map
<String
, CdmPreference
> cache
= new ConcurrentHashMap
<>();
51 private boolean cacheIsComplete
= false;
53 private boolean cacheIsLocked
= false;
56 public CdmPreference
findExact(PrefKey key
) {
57 String cacheKey
= cacheKey(key
);
58 return fromCacheGet(key
, cacheKey
);
62 public CdmPreference
find(PrefKey key
) {
63 CdmPreference pref
= PreferenceResolver
.resolve(list(), key
);
68 public CdmPreference
findDatabase(IPreferencePredicate
<?
> predicate
){
69 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewDatabaseInstance(), predicate
);
74 public CdmPreference
findVaadin(IPreferencePredicate
<?
> predicate
){
75 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewVaadinInstance(), predicate
);
80 public CdmPreference
findTaxEditor(IPreferencePredicate
<?
> predicate
){
81 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewTaxEditorInstance(), predicate
);
86 @Transactional(readOnly
= false)
87 public void set(CdmPreference preference
) {
93 @Transactional(readOnly
= false)
94 public void remove(PrefKey key
) {
100 public long count() {
105 public List
<CdmPreference
> list() {
106 if(!cacheIsComplete
) {
109 return new ArrayList
<>(cacheValues());
113 public List
<CdmPreference
> list(IPreferencePredicate
<?
> predicate
) {
114 // using the cache for this method makes not much sense
115 return dao
.list(predicate
);
119 public CdmPreference
find(TaxonNode taxonNode
, String predicate
) {
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);
129 public CdmPreference
find(TaxonNode taxonNode
, IPreferencePredicate
<?
> predicate
){
130 return find(taxonNode
, predicate
.getKey());
133 // ********************** NOT YET HANDLED *******************/
136 public List
<CdmPreference
> list(String subject
, String predicate
) {
138 throw new RuntimeException("list(String, String) not yet implemented" );
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
);
148 private TaxonNode
mapToTaxonNode(CdmBase taxonNodeRelatedCdmBase
) {
149 if (taxonNodeRelatedCdmBase
== null){
151 }else if (taxonNodeRelatedCdmBase
.isInstanceOf(TaxonNode
.class)){
152 return CdmBase
.deproxy(taxonNodeRelatedCdmBase
, TaxonNode
.class);
154 throw new RuntimeException("mapToTaxonNode not yet implemented for " + taxonNodeRelatedCdmBase
.getClass().getSimpleName());
158 // ====================== Cache methods ======================= //
161 * Concatenates subject and predicate as key for the cache map
163 private String
cacheKey(PrefKey key
) {
164 return key
.getSubject() + "@" + key
.getPredicate();
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
172 private String
cacheKey(TaxonNode taxonNode
, String predicate
) {
173 return taxonNode
.treeIndex() + predicate
;
177 // --------------- non locking cache read methods --------------- //
179 protected Collection
<CdmPreference
> cacheValues() {
181 return cache
.values();
184 protected CdmPreference
fromCacheGet(PrefKey key
, String cacheKey
) {
186 return cache
.computeIfAbsent(cacheKey
, k
-> dao
.get(key
));
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
195 protected CdmPreference
fromCacheOrFind(TaxonNode taxonNode
, String predicate
, String cacheKey
) {
197 return cache
.computeIfAbsent(cacheKey
, k
-> dao
.find(taxonNode
, predicate
));
200 // --------------- cache locking methods --------------- //
202 protected void cachePut(CdmPreference preference
) {
204 cacheIsLocked
= true;
205 cache
.put(cacheKey(preference
.getKey()), preference
);
206 cacheIsLocked
= false;
210 protected void removeFromCache(PrefKey key
) {
212 cacheIsLocked
= true;
213 cache
.remove(cacheKey(key
));
214 cacheIsLocked
= false;
217 protected void cacheFullUpdate() {
219 cacheIsLocked
= true;
221 for(CdmPreference pref
: dao
.list()){
222 cache
.put(cacheKey(pref
.getKey()), pref
);
224 cacheIsComplete
= true;
225 cacheIsLocked
= false;
228 protected void waitForCache() {
229 while(cacheIsLocked
) {
232 } catch (InterruptedException e
) {
233 // just keep on sleeping, we may improve this later on