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
;
37 @Transactional(readOnly
= true)
38 public class PreferenceServiceImpl
implements IPreferenceService
{
40 @SuppressWarnings("unused")
41 private static final Logger logger
= Logger
.getLogger(PreferenceServiceImpl
.class);
44 private IPreferenceDao dao
;
46 private Map
<String
, CdmPreference
> cache
= new ConcurrentHashMap
<>();
48 private boolean cacheIsComplete
= false;
50 private boolean cacheIsLocked
= false;
53 public CdmPreference
findExact(PrefKey key
) {
54 String cacheKey
= cacheKey(key
);
55 return fromCacheGet(key
, cacheKey
);
59 public CdmPreference
find(PrefKey key
) {
60 CdmPreference pref
= PreferenceResolver
.resolve(list(), key
);
65 public CdmPreference
findDatabase(IPreferencePredicate
<?
> predicate
){
66 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewDatabaseInstance(), predicate
);
71 public CdmPreference
findVaadin(IPreferencePredicate
<?
> predicate
){
72 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewVaadinInstance(), predicate
);
77 public CdmPreference
findTaxEditor(IPreferencePredicate
<?
> predicate
){
78 PrefKey key
= CdmPreference
.NewKey(PreferenceSubject
.NewTaxEditorInstance(), predicate
);
83 @Transactional(readOnly
= false)
84 public void set(CdmPreference preference
) {
90 @Transactional(readOnly
= false)
91 public void remove(PrefKey key
) {
102 public List
<CdmPreference
> list() {
103 if(!cacheIsComplete
) {
106 return new ArrayList
<>(cacheValues());
110 public List
<CdmPreference
> list(IPreferencePredicate
<?
> predicate
) {
111 // using the cache for this method makes not much sense
112 return dao
.list(predicate
);
116 public CdmPreference
find(TaxonNode taxonNode
, String predicate
) {
117 String cacheKey
= cacheKey(taxonNode
, predicate
);
118 return fromCacheOrFind(taxonNode
, predicate
, cacheKey
);
122 public CdmPreference
find(TaxonNode taxonNode
, IPreferencePredicate
<?
> predicate
){
123 return find(taxonNode
, predicate
.getKey());
126 // ********************** NOT YET HANDLED *******************/
129 public List
<CdmPreference
> list(String subject
, String predicate
) {
131 throw new RuntimeException("list(String, String) not yet implemented" );
135 //this method is only partly implemented
136 public CdmPreference
find(CdmBase taxonNodeRelatedCdmBase
, String predicate
) {
137 TaxonNode taxonNode
= mapToTaxonNode(taxonNodeRelatedCdmBase
);
138 return dao
.find(taxonNode
, predicate
);
141 private TaxonNode
mapToTaxonNode(CdmBase taxonNodeRelatedCdmBase
) {
142 if (taxonNodeRelatedCdmBase
== null){
144 }else if (taxonNodeRelatedCdmBase
.isInstanceOf(TaxonNode
.class)){
145 return CdmBase
.deproxy(taxonNodeRelatedCdmBase
, TaxonNode
.class);
147 throw new RuntimeException("mapToTaxonNode not yet implemented for " + taxonNodeRelatedCdmBase
.getClass().getSimpleName());
151 // ====================== Cache methods ======================= //
154 * Concatenates subject and predicate as key for the cache map
156 private String
cacheKey(PrefKey key
) {
157 return key
.getSubject() + key
.getPredicate();
160 private String
cacheKey(TaxonNode taxonNode
, String predicate
) {
161 return taxonNode
.treeIndex() + predicate
;
165 // --------------- non locking cache read methods --------------- //
167 protected Collection
<CdmPreference
> cacheValues() {
169 return cache
.values();
172 protected CdmPreference
fromCacheGet(PrefKey key
, String cacheKey
) {
174 return cache
.computeIfAbsent(cacheKey
, k
-> dao
.get(key
));
178 protected CdmPreference
fromCacheOrFind(TaxonNode taxonNode
, String predicate
, String cacheKey
) {
180 return cache
.computeIfAbsent(cacheKey
, k
-> dao
.find(taxonNode
, predicate
));
183 // --------------- cache locking methods --------------- //
185 protected void cachePut(CdmPreference preference
) {
187 cacheIsLocked
= true;
188 cache
.put(cacheKey(preference
.getKey()), preference
);
189 cacheIsLocked
= false;
193 protected void removeFromCache(PrefKey key
) {
195 cacheIsLocked
= true;
196 cache
.remove(cacheKey(key
));
197 cacheIsLocked
= false;
200 protected void cacheFullUpdate() {
202 cacheIsLocked
= true;
204 for(CdmPreference pref
: dao
.list()){
205 cache
.put(cacheKey(pref
.getKey()), pref
);
207 cacheIsLocked
= false;
210 protected void waitForCache() {
211 while(cacheIsLocked
) {
214 } catch (InterruptedException e
) {
215 // just keep on sleeping, we may improve this later on