Merge branch 'release/5.22.0'
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / CommonServiceImpl.java
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 package eu.etaxonomy.cdm.api.service;
10
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.UUID;
18
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;
23
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;
54
55 @Service
56 @Transactional(readOnly = true)
57 public class CommonServiceImpl
58 /*extends ServiceBase<OriginalSourceBase,IOriginalSourceDao>*/
59 implements ICommonService {
60
61 @SuppressWarnings("unused")
62 private static final Logger logger = Logger.getLogger(CommonServiceImpl.class);
63
64 @Autowired
65 private IOriginalSourceDao originalSourceDao;
66
67 @Autowired
68 private ICdmGenericDao genericDao;
69
70 @Override
71 public <T extends CdmBase> T findWithUpdate(Class<T> clazz, int id){
72 return genericDao.find(clazz, id);
73 }
74
75 @Override
76 public <T extends CdmBase> T find(Class<T> clazz, int id){
77 return genericDao.find(clazz, id);
78 }
79
80 @Override
81 public <T extends CdmBase> T find(Class<T> clazz, int id, List<String> propertyPaths){
82 return genericDao.find(clazz, id, propertyPaths);
83 }
84
85 @Override
86 public <T extends CdmBase> T find(Class<T> clazz, UUID uuid) {
87 return uuid == null ? null : genericDao.find(clazz, uuid);
88 }
89
90 @Override
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);
93 }
94
95 @Override
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);
98 return list;
99 }
100
101 @Override
102 public <S extends ISourceable> S getSourcedObjectByIdInSource(Class<S> clazz, String idInSource, String idNamespace) {
103 S result = null;
104 List<S> list = originalSourceDao.findOriginalSourceByIdInSource(clazz, idInSource, idNamespace);
105 if (! list.isEmpty()){
106 result = list.get(0);
107 }return result;
108 }
109
110 @Override
111 public Set<ReferencingObjectDto> getReferencingObjectDtos(CdmBase referencedCdmBase){
112 return this.genericDao.getReferencingObjectsDto(referencedCdmBase);
113 }
114
115 @Override
116 public Set<CdmBase> getReferencingObjects(CdmBase referencedCdmBase){
117 return this.genericDao.getReferencingObjects(referencedCdmBase);
118 }
119
120 @Override
121 public long getReferencingObjectsCount(CdmBase referencedCdmBase){
122 return this.genericDao.getReferencingObjectsCount(referencedCdmBase);
123 }
124
125 @Override
126 public Set<CdmBase> getReferencingObjectsForDeletion(CdmBase referencedCdmBase){
127 return this.genericDao.getReferencingObjectsForDeletion(referencedCdmBase);
128 }
129
130
131 @Override
132 public Set<ReferencingObjectDto> initializeReferencingObjectDtos(Set<ReferencingObjectDto> dtos,
133 boolean doReferencingEntity, boolean doTargetEntity, boolean doDescription, Language language) {
134
135 for (ReferencingObjectDto dto : dtos){
136 //TODO or load()?
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);
141 }
142 if (doTargetEntity){
143 UuidAndTitleCache<CdmBase> target = getReferencingObjectTarget(entity);
144 dto.setOpenInTarget(target);
145 }
146 if (doDescription){
147 String targetString = dto.getOpenInTarget() == null ? null : dto.getOpenInTarget().getTitleCache();
148 String description = getReferencingObjectDescription(entity, targetString, language);
149 dto.setTitleCache(description);
150 }
151 }
152 return dtos;
153 }
154
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;
175 }else{
176 //TODO
177 targetEntity = entity;
178 }
179 }else if (entity instanceof DescriptionBase){
180 targetEntity = getTarget((DescriptionBase)entity);
181 }else{
182 targetEntity = entity;
183 }
184 targetEntity = CdmBase.deproxy(targetEntity);
185 String targetLabel = targetEntity instanceof IdentifiableEntity ? ((IdentifiableEntity)targetEntity).getTitleCache() : null;
186 UuidAndTitleCache<CdmBase> result = new UuidAndTitleCache<>(targetEntity.getClass(), targetEntity.getUuid(), targetEntity.getId(), targetLabel);
187 return result;
188 }
189
190 private CdmBase getTarget(DescriptionElementBase element) {
191 return getTarget(element.getInDescription());
192 }
193
194 private CdmBase getTarget(DescriptionBase db) {
195 return db.describedEntity() != null ? (CdmBase)db.describedEntity() : db;
196 }
197
198 private String getReferencingObjectDescription(CdmBase entity, String targetString, Language language) {
199 return ReferencingObjectFormatter.format(entity, targetString, language);
200 }
201
202 @Override
203 public List getHqlResult(String hqlQuery){
204 return genericDao.getHqlResult(hqlQuery, new Object[0]);
205 }
206
207 @Override
208 public List getHqlResult(String hqlQuery, Object[] params){
209 return genericDao.getHqlResult(hqlQuery, params);
210 }
211
212 @Override
213 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond, IMergeStrategy mergeStrategy) throws MergeException {
214 if (mergeStrategy == null){
215 mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
216 }
217 genericDao.merge((CdmBase)mergeFirst, (CdmBase)mergeSecond, mergeStrategy);
218 }
219
220 @Override
221 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond, Class<? extends CdmBase> clazz) throws MergeException {
222 IMergeStrategy mergeStrategy;
223 if (clazz == null){
224 mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
225 } else {
226 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
227 }
228 merge(mergeFirst, mergeSecond, mergeStrategy);
229 }
230
231 @Override
232 @Transactional(readOnly = false)
233 @Deprecated
234 public <T extends IMergable> void merge(int mergeFirstId, int mergeSecondId, Class<? extends CdmBase> clazz) throws MergeException {
235 IMergeStrategy mergeStrategy;
236 T mergeFirst = (T) genericDao.find(clazz, mergeFirstId);
237 T mergeSecond = (T) genericDao.find(clazz, mergeSecondId);
238 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
239 merge(mergeFirst, mergeSecond, mergeStrategy);
240 }
241
242 @Override
243 @Transactional(readOnly = false)
244 public <T extends IMergable> void merge(UUID mergeFirstUuid, UUID mergeSecondUuid, Class<? extends CdmBase> clazz) throws MergeException {
245 IMergeStrategy mergeStrategy;
246 T mergeFirst = (T) genericDao.find(clazz, mergeFirstUuid);
247 T mergeSecond = (T) genericDao.find(clazz, mergeSecondUuid);
248 if (mergeFirst == null){
249 throw new MergeException("The merge target is not available anymore.");
250 }
251 if (mergeSecond == null){
252 throw new MergeException("The merge candidate is not available anymore.");
253 }
254 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
255 merge(mergeFirst, mergeSecond, mergeStrategy);
256 }
257
258 @Override
259 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond) throws MergeException {
260 IMergeStrategy mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
261 merge(mergeFirst, mergeSecond, mergeStrategy);
262 }
263
264 @Override
265 public <T extends IMatchable> List<T> findMatching(T objectToMatch, IMatchStrategy matchStrategy) throws MatchException {
266 if (matchStrategy == null){
267 matchStrategy = DefaultMatchStrategy.NewInstance(((objectToMatch).getClass()));
268 }
269 return genericDao.findMatching(objectToMatch, matchStrategy);
270 }
271
272 @Override
273 public <T extends IMatchable> List<T> findMatching(T objectToMatch, MatchStrategy strategy) throws MatchException {
274 return findMatching(objectToMatch, MatchStrategyConfigurator.getMatchStrategy(strategy));
275 }
276
277 @Transactional(readOnly = false)
278 @Override
279 public void saveAllMetaData(Collection<CdmMetaData> metaData) {
280 Iterator<CdmMetaData> iterator = metaData.iterator();
281 while(iterator.hasNext()){
282 CdmMetaData cdmMetaData = iterator.next();
283 genericDao.saveMetaData(cdmMetaData);
284 }
285 }
286
287 @Override
288 public Map<CdmMetaDataPropertyName, CdmMetaData> getCdmMetaData() {
289 Map<CdmMetaDataPropertyName, CdmMetaData> result = new HashMap<>();
290 List<CdmMetaData> metaDataList = genericDao.getMetaData();
291 for (CdmMetaData metaData : metaDataList){
292 CdmMetaDataPropertyName propertyName = metaData.getPropertyName();
293 result.put(propertyName, metaData);
294 }
295 return result;
296 }
297
298 @Override
299 public Object initializeCollection(UUID ownerUuid, String fieldName) {
300 return genericDao.initializeCollection(ownerUuid, fieldName);
301 }
302
303 @Override
304 public Object initializeCollection(UUID ownerUuid, String fieldName, List<String> propertyPaths) {
305 return genericDao.initializeCollection(ownerUuid, fieldName, propertyPaths);
306 }
307
308 @Override
309 public boolean isEmpty(UUID ownerUuid, String fieldName) {
310 return genericDao.isEmpty(ownerUuid, fieldName);
311 }
312
313 @Override
314 public int size(UUID ownerUuid, String fieldName) {
315 return genericDao.size(ownerUuid, fieldName);
316 }
317
318 @Override
319 public Object get(UUID ownerUuid, String fieldName, int index) {
320 return genericDao.get(ownerUuid, fieldName, index);
321 }
322
323 @Override
324 public boolean contains(UUID ownerUuid, String fieldName, Object element) {
325 return genericDao.contains(ownerUuid, fieldName, element);
326 }
327
328 @Override
329 public boolean containsKey(UUID ownerUuid, String fieldName, Object key) {
330 return genericDao.containsKey(ownerUuid, fieldName, key);
331 }
332
333 @Override
334 public boolean containsValue(UUID ownerUuid, String fieldName, Object value) {
335 return genericDao.containsValue(ownerUuid, fieldName, value);
336 }
337
338 @Override
339 @Transactional(readOnly = false)
340 public void createFullSampleData() {
341 genericDao.createFullSampleData();
342 }
343
344 @Override
345 public <S extends CdmBase> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths){
346 return genericDao.list(type, limit, start, orderHints, propertyPaths);
347 }
348
349 @Override
350 public <S extends CdmBase> long count(Class<S> type) {
351 return genericDao.count(type);
352 }
353
354 @Override
355 @Transactional(readOnly = false)
356 public CdmBase save(CdmBase newInstance) {
357 return genericDao.save(newInstance);
358 }
359
360 @Override
361 @Transactional(readOnly = false)
362 public UUID delete(CdmBase instance) {
363 return genericDao.delete(instance);
364 }
365
366 @Override
367 @Transactional(readOnly = false)
368 public UUID saveOrUpdate(CdmBase newInstance) {
369 return genericDao.saveOrUpdate(newInstance);
370 }
371
372 @Override
373 @Transactional(readOnly = false)
374 public <T extends CdmBase> Map<UUID,T> save(Collection<T> newInstances) {
375 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
376 //and generally the saveAll method should work for other CdmBase types with generics removed
377 return (Map<UUID, T>) originalSourceDao.saveAll((Collection)newInstances);
378 }
379
380 @Override
381 @Transactional(readOnly = false)
382 public <T extends CdmBase> Map<UUID,T> saveOrUpdate(Collection<T> newInstances) {
383 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
384 //and generally the saveAll method should work for other CdmBase types with generics removed
385 return (Map<UUID, T>) originalSourceDao.saveOrUpdateAll((Collection)newInstances);
386 }
387
388 @Override
389 public <T extends CdmBase> boolean isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException {
390 return genericDao.isMergeable(cdmBase1, cdmBase2, mergeStrategy);
391 }
392
393 @Override
394 public List<UUID> listUuid(Class<? extends CdmBase> clazz) {
395 return genericDao.listUuid(clazz);
396 }
397
398 @Override
399 @Transactional(readOnly = true)
400 public UUID refresh(CdmBase persistentObject) {
401 return genericDao.refresh(persistentObject);
402 }
403
404 }