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.
9 package eu
.etaxonomy
.cdm
.api
.service
;
11 import java
.util
.Collection
;
12 import java
.util
.HashMap
;
13 import java
.util
.Iterator
;
14 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
21 import org
.springframework
.stereotype
.Service
;
22 import org
.springframework
.transaction
.annotation
.Transactional
;
24 import eu
.etaxonomy
.cdm
.format
.ReferencingObjectFormatter
;
25 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
26 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
27 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
28 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
29 import eu
.etaxonomy
.cdm
.model
.common
.SingleSourcedEntityBase
;
30 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
31 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
32 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
33 import eu
.etaxonomy
.cdm
.model
.metadata
.CdmMetaData
;
34 import eu
.etaxonomy
.cdm
.model
.metadata
.CdmMetaDataPropertyName
;
35 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalSource
;
36 import eu
.etaxonomy
.cdm
.model
.reference
.ISourceable
;
37 import eu
.etaxonomy
.cdm
.model
.reference
.NamedSource
;
38 import eu
.etaxonomy
.cdm
.model
.taxon
.SecundumSource
;
39 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
40 import eu
.etaxonomy
.cdm
.persistence
.dao
.reference
.IOriginalSourceDao
;
41 import eu
.etaxonomy
.cdm
.persistence
.dto
.ReferencingObjectDto
;
42 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
43 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
44 import eu
.etaxonomy
.cdm
.strategy
.match
.DefaultMatchStrategy
;
45 import eu
.etaxonomy
.cdm
.strategy
.match
.IMatchStrategy
;
46 import eu
.etaxonomy
.cdm
.strategy
.match
.IMatchable
;
47 import eu
.etaxonomy
.cdm
.strategy
.match
.MatchException
;
48 import eu
.etaxonomy
.cdm
.strategy
.match
.MatchStrategyConfigurator
;
49 import eu
.etaxonomy
.cdm
.strategy
.match
.MatchStrategyConfigurator
.MatchStrategy
;
50 import eu
.etaxonomy
.cdm
.strategy
.merge
.DefaultMergeStrategy
;
51 import eu
.etaxonomy
.cdm
.strategy
.merge
.IMergable
;
52 import eu
.etaxonomy
.cdm
.strategy
.merge
.IMergeStrategy
;
53 import eu
.etaxonomy
.cdm
.strategy
.merge
.MergeException
;
56 @Transactional(readOnly
= true)
57 public class CommonServiceImpl
58 /*extends ServiceBase<OriginalSourceBase,IOriginalSourceDao>*/
59 implements ICommonService
{
61 @SuppressWarnings("unused")
62 private static final Logger logger
= Logger
.getLogger(CommonServiceImpl
.class);
65 private IOriginalSourceDao originalSourceDao
;
68 private ICdmGenericDao genericDao
;
71 public <T
extends CdmBase
> T
findWithUpdate(Class
<T
> clazz
, int id
){
72 return genericDao
.find(clazz
, id
);
76 public <T
extends CdmBase
> T
find(Class
<T
> clazz
, int id
){
77 return genericDao
.find(clazz
, id
);
81 public <T
extends CdmBase
> T
find(Class
<T
> clazz
, int id
, List
<String
> propertyPaths
){
82 return genericDao
.find(clazz
, id
, propertyPaths
);
86 public <T
extends CdmBase
> T
find(Class
<T
> clazz
, UUID uuid
) {
87 return uuid
== null ?
null : genericDao
.find(clazz
, uuid
);
91 public <T
extends CdmBase
> T
find(Class
<T
> clazz
, UUID uuid
, List
<String
> propertyPaths
) {
92 return uuid
== null ?
null : genericDao
.find(clazz
, uuid
, propertyPaths
);
96 public <S
extends ISourceable
> Map
<String
, S
> getSourcedObjectsByIdInSourceC(Class
<S
> clazz
, Set
<String
> idInSourceSet
, String idNamespace
){
97 Map
<String
, S
> list
= originalSourceDao
.findOriginalSourcesByIdInSource(clazz
, idInSourceSet
, idNamespace
);
102 public <S
extends ISourceable
> S
getSourcedObjectByIdInSource(Class
<S
> clazz
, String idInSource
, String idNamespace
) {
104 List
<S
> list
= originalSourceDao
.findOriginalSourceByIdInSource(clazz
, idInSource
, idNamespace
);
105 if (! list
.isEmpty()){
106 result
= list
.get(0);
111 public Set
<ReferencingObjectDto
> getReferencingObjectDtos(CdmBase referencedCdmBase
){
112 return this.genericDao
.getReferencingObjectsDto(referencedCdmBase
);
116 public Set
<CdmBase
> getReferencingObjects(CdmBase referencedCdmBase
){
117 return this.genericDao
.getReferencingObjects(referencedCdmBase
);
121 public long getReferencingObjectsCount(CdmBase referencedCdmBase
){
122 return this.genericDao
.getReferencingObjectsCount(referencedCdmBase
);
126 public Set
<CdmBase
> getReferencingObjectsForDeletion(CdmBase referencedCdmBase
){
127 return this.genericDao
.getReferencingObjectsForDeletion(referencedCdmBase
);
132 public Set
<ReferencingObjectDto
> initializeReferencingObjectDtos(Set
<ReferencingObjectDto
> dtos
,
133 boolean doReferencingEntity
, boolean doTargetEntity
, boolean doDescription
, Language language
) {
135 for (ReferencingObjectDto dto
: dtos
){
137 CdmBase entity
= this.genericDao
.find(dto
.getType(), dto
.getUuid());
138 entity
= CdmBase
.deproxy(entity
); //TODO necessary here or should we only do this in called methods below
139 if (doReferencingEntity
){
140 dto
.setReferencedEntity(entity
);
143 UuidAndTitleCache
<CdmBase
> target
= getReferencingObjectTarget(entity
);
144 dto
.setOpenInTarget(target
);
147 String targetString
= dto
.getOpenInTarget() == null ?
null : dto
.getOpenInTarget().getTitleCache();
148 String description
= getReferencingObjectDescription(entity
, targetString
, language
);
149 dto
.setTitleCache(description
);
155 private UuidAndTitleCache
<CdmBase
> getReferencingObjectTarget(CdmBase entity
) {
156 CdmBase targetEntity
;
157 entity
= CdmBase
.deproxy(entity
);
158 if (entity
instanceof SecundumSource
){
159 targetEntity
= ((SecundumSource
) entity
).getSourcedTaxon();
160 }else if (entity
instanceof NomenclaturalSource
){
161 targetEntity
= ((NomenclaturalSource
) entity
).getSourcedName();
162 }else if (entity
instanceof DescriptionElementSource
){
163 DescriptionElementBase element
= ((DescriptionElementSource
) entity
).getSourcedElement();
164 targetEntity
= getTarget(element
);
165 }else if (entity
instanceof DescriptionElementBase
){
166 targetEntity
= getTarget((DescriptionElementBase
)entity
);
167 }else if (entity
instanceof IdentifiableSource
){
168 IdentifiableSource source
= ((IdentifiableSource
) entity
);
169 targetEntity
= originalSourceDao
.findIdentifiableBySourceId(IdentifiableEntity
.class, source
.getId());
170 }else if (entity
instanceof NamedSource
){
171 NamedSource source
= ((NamedSource
) entity
);
172 SingleSourcedEntityBase singleSourced
= originalSourceDao
.findSingleSourceBySourceId(SingleSourcedEntityBase
.class, source
.getId());
173 if (singleSourced
!= null){
174 targetEntity
= singleSourced
;
177 targetEntity
= entity
;
179 }else if (entity
instanceof DescriptionBase
){
180 targetEntity
= getTarget((DescriptionBase
)entity
);
182 targetEntity
= entity
;
184 targetEntity
= CdmBase
.deproxy(targetEntity
);
186 if (targetEntity
== null){
187 targetEntity
= entity
;
189 String targetLabel
= targetEntity
instanceof IdentifiableEntity ?
((IdentifiableEntity
<?
>)targetEntity
).getTitleCache() : null;
190 UuidAndTitleCache
<CdmBase
> result
= new UuidAndTitleCache
<>(targetEntity
.getClass(), targetEntity
.getUuid(), targetEntity
.getId(), targetLabel
);
194 private CdmBase
getTarget(DescriptionElementBase element
) {
195 return getTarget(element
.getInDescription());
198 private CdmBase
getTarget(DescriptionBase db
) {
199 return db
.describedEntity() != null ?
(CdmBase
)db
.describedEntity() : db
;
202 private String
getReferencingObjectDescription(CdmBase entity
, String targetString
, Language language
) {
203 return ReferencingObjectFormatter
.format(entity
, targetString
, language
);
207 public List
getHqlResult(String hqlQuery
){
208 return genericDao
.getHqlResult(hqlQuery
, new Object
[0]);
212 public List
getHqlResult(String hqlQuery
, Object
[] params
){
213 return genericDao
.getHqlResult(hqlQuery
, params
);
217 public <T
extends IMergable
> void merge(T mergeFirst
, T mergeSecond
, IMergeStrategy mergeStrategy
) throws MergeException
{
218 if (mergeStrategy
== null){
219 mergeStrategy
= DefaultMergeStrategy
.NewInstance(((CdmBase
)mergeFirst
).getClass());
221 genericDao
.merge((CdmBase
)mergeFirst
, (CdmBase
)mergeSecond
, mergeStrategy
);
225 public <T
extends IMergable
> void merge(T mergeFirst
, T mergeSecond
, Class
<?
extends CdmBase
> clazz
) throws MergeException
{
226 IMergeStrategy mergeStrategy
;
228 mergeStrategy
= DefaultMergeStrategy
.NewInstance(((CdmBase
)mergeFirst
).getClass());
230 mergeStrategy
= DefaultMergeStrategy
.NewInstance(clazz
);
232 merge(mergeFirst
, mergeSecond
, mergeStrategy
);
236 @Transactional(readOnly
= false)
238 public <T
extends IMergable
> void merge(int mergeFirstId
, int mergeSecondId
, Class
<?
extends CdmBase
> clazz
) throws MergeException
{
239 IMergeStrategy mergeStrategy
;
240 T mergeFirst
= (T
) genericDao
.find(clazz
, mergeFirstId
);
241 T mergeSecond
= (T
) genericDao
.find(clazz
, mergeSecondId
);
242 mergeStrategy
= DefaultMergeStrategy
.NewInstance(clazz
);
243 merge(mergeFirst
, mergeSecond
, mergeStrategy
);
247 @Transactional(readOnly
= false)
248 public <T
extends IMergable
> void merge(UUID mergeFirstUuid
, UUID mergeSecondUuid
, Class
<?
extends CdmBase
> clazz
) throws MergeException
{
249 IMergeStrategy mergeStrategy
;
250 T mergeFirst
= (T
) genericDao
.find(clazz
, mergeFirstUuid
);
251 T mergeSecond
= (T
) genericDao
.find(clazz
, mergeSecondUuid
);
252 if (mergeFirst
== null){
253 throw new MergeException("The merge target is not available anymore.");
255 if (mergeSecond
== null){
256 throw new MergeException("The merge candidate is not available anymore.");
258 mergeStrategy
= DefaultMergeStrategy
.NewInstance(clazz
);
259 merge(mergeFirst
, mergeSecond
, mergeStrategy
);
263 public <T
extends IMergable
> void merge(T mergeFirst
, T mergeSecond
) throws MergeException
{
264 IMergeStrategy mergeStrategy
= DefaultMergeStrategy
.NewInstance(((CdmBase
)mergeFirst
).getClass());
265 merge(mergeFirst
, mergeSecond
, mergeStrategy
);
269 public <T
extends IMatchable
> List
<T
> findMatching(T objectToMatch
, IMatchStrategy matchStrategy
) throws MatchException
{
270 if (matchStrategy
== null){
271 matchStrategy
= DefaultMatchStrategy
.NewInstance(((objectToMatch
).getClass()));
273 return genericDao
.findMatching(objectToMatch
, matchStrategy
);
277 public <T
extends IMatchable
> List
<T
> findMatching(T objectToMatch
, MatchStrategy strategy
) throws MatchException
{
278 return findMatching(objectToMatch
, MatchStrategyConfigurator
.getMatchStrategy(strategy
));
281 @Transactional(readOnly
= false)
283 public void saveAllMetaData(Collection
<CdmMetaData
> metaData
) {
284 Iterator
<CdmMetaData
> iterator
= metaData
.iterator();
285 while(iterator
.hasNext()){
286 CdmMetaData cdmMetaData
= iterator
.next();
287 genericDao
.saveMetaData(cdmMetaData
);
292 public Map
<CdmMetaDataPropertyName
, CdmMetaData
> getCdmMetaData() {
293 Map
<CdmMetaDataPropertyName
, CdmMetaData
> result
= new HashMap
<>();
294 List
<CdmMetaData
> metaDataList
= genericDao
.getMetaData();
295 for (CdmMetaData metaData
: metaDataList
){
296 CdmMetaDataPropertyName propertyName
= metaData
.getPropertyName();
297 result
.put(propertyName
, metaData
);
303 public Object
initializeCollection(UUID ownerUuid
, String fieldName
) {
304 return genericDao
.initializeCollection(ownerUuid
, fieldName
);
308 public Object
initializeCollection(UUID ownerUuid
, String fieldName
, List
<String
> propertyPaths
) {
309 return genericDao
.initializeCollection(ownerUuid
, fieldName
, propertyPaths
);
313 public boolean isEmpty(UUID ownerUuid
, String fieldName
) {
314 return genericDao
.isEmpty(ownerUuid
, fieldName
);
318 public int size(UUID ownerUuid
, String fieldName
) {
319 return genericDao
.size(ownerUuid
, fieldName
);
323 public Object
get(UUID ownerUuid
, String fieldName
, int index
) {
324 return genericDao
.get(ownerUuid
, fieldName
, index
);
328 public boolean contains(UUID ownerUuid
, String fieldName
, Object element
) {
329 return genericDao
.contains(ownerUuid
, fieldName
, element
);
333 public boolean containsKey(UUID ownerUuid
, String fieldName
, Object key
) {
334 return genericDao
.containsKey(ownerUuid
, fieldName
, key
);
338 public boolean containsValue(UUID ownerUuid
, String fieldName
, Object value
) {
339 return genericDao
.containsValue(ownerUuid
, fieldName
, value
);
343 @Transactional(readOnly
= false)
344 public void createFullSampleData() {
345 genericDao
.createFullSampleData();
349 public <S
extends CdmBase
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
350 return genericDao
.list(type
, limit
, start
, orderHints
, propertyPaths
);
354 public <S
extends CdmBase
> long count(Class
<S
> type
) {
355 return genericDao
.count(type
);
359 @Transactional(readOnly
= false)
360 public CdmBase
save(CdmBase newInstance
) {
361 return genericDao
.save(newInstance
);
365 @Transactional(readOnly
= false)
366 public UUID
delete(CdmBase instance
) {
367 return genericDao
.delete(instance
);
371 @Transactional(readOnly
= false)
372 public UUID
saveOrUpdate(CdmBase newInstance
) {
373 return genericDao
.saveOrUpdate(newInstance
);
377 @Transactional(readOnly
= false)
378 public <T
extends CdmBase
> Map
<UUID
,T
> save(Collection
<T
> newInstances
) {
379 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
380 //and generally the saveAll method should work for other CdmBase types with generics removed
381 return (Map
<UUID
, T
>) originalSourceDao
.saveAll((Collection
)newInstances
);
385 @Transactional(readOnly
= false)
386 public <T
extends CdmBase
> Map
<UUID
,T
> saveOrUpdate(Collection
<T
> newInstances
) {
387 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
388 //and generally the saveAll method should work for other CdmBase types with generics removed
389 return (Map
<UUID
, T
>) originalSourceDao
.saveOrUpdateAll((Collection
)newInstances
);
393 public <T
extends CdmBase
> boolean isMergeable(T cdmBase1
, T cdmBase2
, IMergeStrategy mergeStrategy
) throws MergeException
{
394 return genericDao
.isMergeable(cdmBase1
, cdmBase2
, mergeStrategy
);
398 public List
<UUID
> listUuid(Class
<?
extends CdmBase
> clazz
) {
399 return genericDao
.listUuid(clazz
);
403 @Transactional(readOnly
= true)
404 public UUID
refresh(CdmBase persistentObject
) {
405 return genericDao
.refresh(persistentObject
);