3 * Copyright (C) 2007 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.
11 package eu
.etaxonomy
.cdm
.api
.service
;
13 import java
.util
.ArrayList
;
14 import java
.util
.List
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.hibernate
.criterion
.Criterion
;
18 import org
.springframework
.transaction
.annotation
.Transactional
;
20 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
21 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
22 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
23 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
24 import eu
.etaxonomy
.cdm
.model
.common
.ISourceable
;
25 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
26 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
27 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
28 import eu
.etaxonomy
.cdm
.model
.common
.UuidAndTitleCache
;
29 import eu
.etaxonomy
.cdm
.model
.media
.Rights
;
30 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
31 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
32 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IIdentifiableDao
;
33 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
34 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
35 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
37 public abstract class IdentifiableServiceBase
<T
extends IdentifiableEntity
,DAO
extends IIdentifiableDao
<T
>> extends AnnotatableServiceBase
<T
,DAO
>
38 implements IIdentifiableEntityService
<T
>{
40 protected static final int UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE
= 1000;
41 protected static final Logger logger
= Logger
.getLogger(IdentifiableServiceBase
.class);
43 @Transactional(readOnly
= true)
44 public Pager
<Rights
> getRights(T t
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
45 Integer numberOfResults
= dao
.countRights(t
);
47 List
<Rights
> results
= new ArrayList
<Rights
>();
48 if(numberOfResults
> 0) { // no point checking again
49 results
= dao
.getRights(t
, pageSize
, pageNumber
,propertyPaths
);
52 return new DefaultPagerImpl
<Rights
>(pageNumber
, numberOfResults
, pageSize
, results
);
55 @Transactional(readOnly
= true)
56 public Pager
<IdentifiableSource
> getSources(T t
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
57 Integer numberOfResults
= dao
.countSources(t
);
59 List
<IdentifiableSource
> results
= new ArrayList
<IdentifiableSource
>();
60 if(numberOfResults
> 0) { // no point checking again
61 results
= dao
.getSources(t
, pageSize
, pageNumber
,propertyPaths
);
64 return new DefaultPagerImpl
<IdentifiableSource
>(pageNumber
, numberOfResults
, pageSize
, results
);
67 @Transactional(readOnly
= true)
68 protected List
<T
> findByTitle(IIdentifiableEntityServiceConfigurator config
){
69 return ((IIdentifiableDao
)dao
).findByTitle(config
.getTitleSearchString(),
70 config
.getMatchMode(), 0, -1, null);
71 // TODO: Implement parameters pageSize, pageNumber, and criteria
74 @Transactional(readOnly
= false)
75 public T
replace(T x
, T y
) {
76 return dao
.replace(x
, y
);
79 * FIXME Candidate for harmonization
80 * Given that this method is strongly typed, and generic, could we not simply expose it as
81 * List<T> findByTitle(String title) as it is somewhat less cumbersome. Admittedly, I don't
82 * understand what is going on with the configurators etc. so maybe there is a good reason for
83 * the design of this method.
87 @Transactional(readOnly
= true)
88 protected List
<T
> findCdmObjectsByTitle(String title
){
89 return ((IIdentifiableDao
)dao
).findByTitle(title
);
92 @Transactional(readOnly
= true)
93 protected List
<T
> findCdmObjectsByTitle(String title
, Class
<T
> clazz
){
94 return ((IIdentifiableDao
)dao
).findByTitleAndClass(title
, clazz
);
96 @Transactional(readOnly
= true)
97 protected List
<T
> findCdmObjectsByTitle(String title
, CdmBase sessionObject
){
98 return ((IIdentifiableDao
)dao
).findByTitle(title
, sessionObject
);
102 * TODO - Migrated from CommonServiceBase
104 * @see eu.etaxonomy.cdm.api.service.ICommonService#getSourcedObjectById(java.lang.String, java.lang.String)
106 @Transactional(readOnly
= true)
107 public ISourceable
getSourcedObjectByIdInSource(Class clazz
, String idInSource
, String idNamespace
) {
108 ISourceable result
= null;
110 List
<T
> list
= dao
.findOriginalSourceByIdInSource(idInSource
, idNamespace
);
111 if (! list
.isEmpty()){
112 result
= list
.get(0);
118 * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#getUuidAndTitleCache()
120 @Transactional(readOnly
= true)
121 public List
<UuidAndTitleCache
<T
>> getUuidAndTitleCache() {
122 return dao
.getUuidAndTitleCache();
125 @Transactional(readOnly
= true)
126 public Pager
<T
> findByTitle(Class
<?
extends T
> clazz
, String queryString
,MatchMode matchmode
, List
<Criterion
> criteria
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
127 Integer numberOfResults
= dao
.countByTitle(clazz
, queryString
, matchmode
, criteria
);
129 List
<T
> results
= new ArrayList
<T
>();
130 if(numberOfResults
> 0) { // no point checking again
131 results
= dao
.findByTitle(clazz
, queryString
, matchmode
, criteria
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
134 return new DefaultPagerImpl
<T
>(pageNumber
, numberOfResults
, pageSize
, results
);
137 @Transactional(readOnly
= true)
138 public List
<T
> listByTitle(Class
<?
extends T
> clazz
, String queryString
,MatchMode matchmode
, List
<Criterion
> criteria
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
139 Integer numberOfResults
= dao
.countByTitle(clazz
, queryString
, matchmode
, criteria
);
141 List
<T
> results
= new ArrayList
<T
>();
142 if(numberOfResults
> 0) { // no point checking again
143 results
= dao
.findByTitle(clazz
, queryString
, matchmode
, criteria
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
148 @Transactional(readOnly
= true)
149 public List
<T
> listByReferenceTitle(Class
<?
extends T
> clazz
, String queryString
,MatchMode matchmode
, List
<Criterion
> criteria
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
150 Integer numberOfResults
= dao
.countByTitle(clazz
, queryString
, matchmode
, criteria
);
152 List
<T
> results
= new ArrayList
<T
>();
153 if(numberOfResults
> 0) { // no point checking again
154 results
= dao
.findByReferenceTitle(clazz
, queryString
, matchmode
, criteria
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
159 @Transactional(readOnly
= true)
160 public T
find(LSID lsid
) {
161 return dao
.find(lsid
);
164 @Transactional(readOnly
= true)
165 public Pager
<T
> search(Class
<?
extends T
> clazz
, String queryString
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
166 Integer numberOfResults
= dao
.count(clazz
,queryString
);
168 List
<T
> results
= new ArrayList
<T
>();
169 if(numberOfResults
> 0) { // no point checking again
170 results
= dao
.search(clazz
,queryString
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
173 return new DefaultPagerImpl
<T
>(pageNumber
, numberOfResults
, pageSize
, results
);
176 @Transactional(readOnly
= false)
177 public void updateTitleCache(Class
<?
extends T
> clazz
) {
178 IIdentifiableEntityCacheStrategy
<T
> cacheStrategy
= null;
179 updateTitleCache(clazz
, UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE
, cacheStrategy
);
183 @Transactional(readOnly
= false) //TODO check transactional behaviour, e.g. what happens with the session if count is very large
184 public void updateTitleCache(Class
<?
extends T
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<T
> cacheStrategy
) {
185 if (stepSize
== null){
186 stepSize
= UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE
;
189 int count
= dao
.count(clazz
);
190 for(int i
= 0 ; i
< count
; i
= i
+ stepSize
){
191 // not sure if such strict ordering is necessary here, but for safety reasons I do it
192 ArrayList
<OrderHint
> orderHints
= new ArrayList
<OrderHint
>();
193 orderHints
.add( new OrderHint("id", OrderHint
.SortOrder
.ASCENDING
));
194 List
<T
> list
= this.list(clazz
, stepSize
, i
, orderHints
, null);
195 List
<T
> entitiesToUpdate
= new ArrayList
<T
>();
196 for (T entity
: list
){
197 if (entity
.isProtectedTitleCache() == false){
198 IIdentifiableEntityCacheStrategy entityCacheStrategy
= cacheStrategy
;
199 if (entityCacheStrategy
== null){
200 entityCacheStrategy
= entity
.getCacheStrategy();
201 //FIXME find out why the wrong cache strategy is loaded here, see #1876
202 if (entity
instanceof ReferenceBase
){
203 entityCacheStrategy
= ReferenceFactory
.newReference(((ReferenceBase
)entity
).getType()).getCacheStrategy();
206 entity
.setCacheStrategy(entityCacheStrategy
);
207 //TODO this won't work for those classes that always generate the title cache new
208 String titleCache
= entity
.getTitleCache();
209 setOtherCachesNull(entity
); //TODO find better solution
210 String newTitleCache
= entityCacheStrategy
.getTitleCache(entity
);
211 if (titleCache
== null || titleCache
!= null && ! titleCache
.equals(newTitleCache
)){
212 entity
.setTitleCache(null, false);
213 entity
.getTitleCache();
214 entitiesToUpdate
.add(entity
);
218 saveOrUpdate(entitiesToUpdate
);
224 * Needs override if not only the title cache should be set to null to
225 * generate the correct new title cache
227 protected void setOtherCachesNull(T entity
) {