ref #1445: improve search for identical names
[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
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.apache.log4j.Logger;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Service;
23 import org.springframework.transaction.annotation.Transactional;
24
25 import eu.etaxonomy.cdm.model.common.CdmBase;
26 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
27 import eu.etaxonomy.cdm.model.metadata.CdmMetaDataPropertyName;
28 import eu.etaxonomy.cdm.model.reference.ISourceable;
29 import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
30 import eu.etaxonomy.cdm.persistence.dao.reference.IOriginalSourceDao;
31 import eu.etaxonomy.cdm.persistence.query.OrderHint;
32 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
33 import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
34 import eu.etaxonomy.cdm.strategy.match.IMatchable;
35 import eu.etaxonomy.cdm.strategy.match.MatchException;
36 import eu.etaxonomy.cdm.strategy.match.MatchStrategyConfigurator;
37 import eu.etaxonomy.cdm.strategy.match.MatchStrategyConfigurator.MatchStrategy;
38 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
39 import eu.etaxonomy.cdm.strategy.merge.IMergable;
40 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
41 import eu.etaxonomy.cdm.strategy.merge.MergeException;
42
43
44 @Service
45 @Transactional(readOnly = true)
46 public class CommonServiceImpl
47 /*extends ServiceBase<OriginalSourceBase,IOriginalSourceDao>*/
48 implements ICommonService {
49
50 @SuppressWarnings("unused")
51 private static final Logger logger = Logger.getLogger(CommonServiceImpl.class);
52
53
54 @Autowired
55 private IOriginalSourceDao originalSourceDao;
56
57
58 @Autowired
59 private ICdmGenericDao genericDao;
60
61
62 @Override
63 public <T extends CdmBase> T findWithUpdate(Class<T> clazz, int id){
64 return genericDao.find(clazz, id);
65 }
66
67 @Override
68 public <T extends CdmBase> T find(Class<T> clazz, int id){
69 return genericDao.find(clazz, id);
70 }
71
72 @Override
73 public <T extends CdmBase> T find(Class<T> clazz, int id, List<String> propertyPaths){
74 return genericDao.find(clazz, id, propertyPaths);
75 }
76
77 @Override
78 public <T extends CdmBase> T find(Class<T> clazz, UUID uuid) {
79 return uuid == null ? null : genericDao.find(clazz, uuid);
80 }
81
82 @Override
83 public <T extends CdmBase> T find(Class<T> clazz, UUID uuid, List<String> propertyPaths) {
84 return uuid == null ? null : genericDao.find(clazz, uuid, propertyPaths);
85 }
86
87 @Override
88 public <S extends ISourceable> Map<String, S> getSourcedObjectsByIdInSourceC(Class<S> clazz, Set<String> idInSourceSet, String idNamespace){
89 Map<String, S> list = originalSourceDao.findOriginalSourcesByIdInSource(clazz, idInSourceSet, idNamespace);
90 return list;
91 }
92
93
94 @Override
95 public <S extends ISourceable> S getSourcedObjectByIdInSource(Class<S> clazz, String idInSource, String idNamespace) {
96 S result = null;
97 List<S> list = originalSourceDao.findOriginalSourceByIdInSource(clazz, idInSource, idNamespace);
98 if (! list.isEmpty()){
99 result = list.get(0);
100 }return result;
101 }
102
103
104 @Override
105 public Set<CdmBase> getReferencingObjects(CdmBase referencedCdmBase){
106 return this.genericDao.getReferencingObjects(referencedCdmBase);
107 }
108
109 @Override
110 public long getReferencingObjectsCount(CdmBase referencedCdmBase){
111 return this.genericDao.getReferencingObjectsCount(referencedCdmBase);
112 }
113
114 @Override
115 public Set<CdmBase> getReferencingObjectsForDeletion(CdmBase referencedCdmBase){
116 return this.genericDao.getReferencingObjectsForDeletion(referencedCdmBase);
117 }
118 // try {
119 // Set<Class<? extends CdmBase>> allCdmClasses = genericDao.getAllCdmClasses(false); //findAllCdmClasses();
120 //
121 // referencedCdmBase = (CdmBase)HibernateProxyHelper.deproxy(referencedCdmBase);
122 // Class referencedClass = referencedCdmBase.getClass();
123 // Set<CdmBase> result = new HashSet<>();
124 // logger.debug("Referenced Class: " + referencedClass.getName());
125 //
126 // for (Class<? extends CdmBase> cdmClass : allCdmClasses){
127 // Set<Field> fields = getFields(cdmClass);
128 // for (Field field: fields){
129 // Class<?> type = field.getType();
130 // //class
131 // if (! type.isInterface()){
132 // if (referencedClass.isAssignableFrom(type)||
133 // type.isAssignableFrom(referencedClass) && CdmBase.class.isAssignableFrom(type)){
134 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
135 // }
136 // //interface
137 // }else if (type.isAssignableFrom(referencedClass)){
138 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, false);
139 // }else if (Collection.class.isAssignableFrom(type)){
140 //
141 // if (checkIsSetOfType(field, referencedClass, type) == true){
142 // handleSingleClass(referencedClass, type, field, cdmClass, result, referencedCdmBase, true);
143 // }
144 // }
145 //// Class[] interfaces = referencedClass.getInterfaces();
146 //// for (Class interfaze: interfaces){
147 //// if (interfaze == type){
148 ////// if(interfaze.isAssignableFrom(returnType)){
149 //// handleSingleClass(interfaze, type, field, cdmClass, result, referencedCdmBase);
150 //// }
151 //// }
152 // }
153 // }
154 // return result;
155 // } catch (Exception e) {
156 // e.printStackTrace();
157 // throw new RuntimeException(e);
158 // }
159 //
160 // }
161 //
162 // private boolean checkIsSetOfType(Field field, Class referencedClass, Class<?> type){
163 // Type genericType = (ParameterizedTypeImpl)field.getGenericType();
164 // if (genericType instanceof ParameterizedTypeImpl){
165 // ParameterizedTypeImpl paraType = (ParameterizedTypeImpl)genericType;
166 // paraType.getRawType();
167 // Type[] arguments = paraType.getActualTypeArguments();
168 // //logger.debug(arguments.length);
169 // if (arguments.length == 1){
170 // Class collectionClass;
171 // try {
172 // if (arguments[0] instanceof Class){
173 // collectionClass = (Class)arguments[0];
174 // }else if(arguments[0] instanceof TypeVariableImpl){
175 // TypeVariableImpl typeVariable = (TypeVariableImpl)arguments[0];
176 // GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
177 // collectionClass = (Class)genericDeclaration;
178 // }else{
179 // logger.warn("Unknown Type");
180 // return false;
181 // }
182 // if (CdmBase.class.isAssignableFrom(collectionClass) && collectionClass.isAssignableFrom(referencedClass) ){
183 // return true;
184 // }
185 // } catch (Exception e) {
186 // logger.warn(e.getMessage());
187 // }
188 // }else{
189 // logger.warn("Length of arguments <> 1");
190 // }
191 // }else{
192 // logger.warn("Not a generic type of type ParameterizedTypeImpl");
193 // }
194 // return false;
195 // }
196 //
197 //
198 //
199 //
200 // private boolean handleSingleClass(Class itemClass, Class type, Field field, Class cdmClass, Set<CdmBase> result,CdmBase value, boolean isCollection){
201 // if (! Modifier.isStatic(field.getModifiers())){
202 // String methodName = StringUtils.rightPad(field.getName(), 30);
203 // String className = StringUtils.rightPad(cdmClass.getSimpleName(), 30);
204 // String returnTypeName = StringUtils.rightPad(type.getSimpleName(), 30);
205 //
206 // logger.debug(methodName + "\t\t" + className + "\t\t" + returnTypeName);
207 //// result_old.add(method);
208 // result.addAll(getCdmBasesByFieldAndClass(field, itemClass, cdmClass, value, isCollection));
209 // }
210 // return true;
211 // }
212 //
213 // private Set<Field> getFields(Class clazz){
214 // Set<Field> result = new HashSet<>();
215 // for (Field field: clazz.getDeclaredFields()){
216 // if (!Modifier.isStatic(field.getModifiers())){
217 // result.add(field);
218 // }
219 // }
220 // Class superclass = clazz.getSuperclass();
221 // if (CdmBase.class.isAssignableFrom(superclass)){
222 // result.addAll(getFields(superclass));
223 // }
224 // return result;
225 // }
226 //
227 // private Set<CdmBase> getCdmBasesByFieldAndClass(Field field, Class itemClass, Class otherClazz, CdmBase item, boolean isCollection){
228 // Set<CdmBase> result = new HashSet<>();
229 // if (isCollection){
230 // result.addAll(genericDao.getCdmBasesWithItemInCollection(itemClass, otherClazz, field.getName(), item));
231 // }else{
232 // result.addAll(genericDao.getCdmBasesByFieldAndClass(otherClazz, field.getName(), item));
233 // }
234 // return result;
235 // }
236
237 @Override
238 public List getHqlResult(String hqlQuery){
239 return genericDao.getHqlResult(hqlQuery);
240 }
241
242 @Override
243 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond, IMergeStrategy mergeStrategy) throws MergeException {
244 if (mergeStrategy == null){
245 mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
246 }
247 genericDao.merge((CdmBase)mergeFirst, (CdmBase)mergeSecond, mergeStrategy);
248 }
249
250 @Override
251 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond, Class<? extends CdmBase> clazz) throws MergeException {
252 IMergeStrategy mergeStrategy;
253 if (clazz == null){
254 mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
255 } else {
256 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
257 }
258 merge(mergeFirst, mergeSecond, mergeStrategy);
259 }
260
261 @Override
262 @Transactional(readOnly = false)
263 @Deprecated
264 public <T extends IMergable> void merge(int mergeFirstId, int mergeSecondId, Class<? extends CdmBase> clazz) throws MergeException {
265 IMergeStrategy mergeStrategy;
266 T mergeFirst = (T) genericDao.find(clazz, mergeFirstId);
267 T mergeSecond = (T) genericDao.find(clazz, mergeSecondId);
268 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
269 merge(mergeFirst, mergeSecond, mergeStrategy);
270 }
271
272 @Override
273 @Transactional(readOnly = false)
274 public <T extends IMergable> void merge(UUID mergeFirstUuid, UUID mergeSecondUuid, Class<? extends CdmBase> clazz) throws MergeException {
275 IMergeStrategy mergeStrategy;
276 T mergeFirst = (T) genericDao.find(clazz, mergeFirstUuid);
277 T mergeSecond = (T) genericDao.find(clazz, mergeSecondUuid);
278 if (mergeFirst == null){
279 throw new MergeException("The merge target is not available anymore.");
280 }
281 if (mergeSecond == null){
282 throw new MergeException("The merge candidate is not available anymore.");
283 }
284 mergeStrategy = DefaultMergeStrategy.NewInstance(clazz);
285 merge(mergeFirst, mergeSecond, mergeStrategy);
286 }
287
288 @Override
289 public <T extends IMergable> void merge(T mergeFirst, T mergeSecond) throws MergeException {
290 IMergeStrategy mergeStrategy = DefaultMergeStrategy.NewInstance(((CdmBase)mergeFirst).getClass());
291 merge(mergeFirst, mergeSecond, mergeStrategy);
292 }
293
294
295 @Override
296 public <T extends IMatchable> List<T> findMatching(T objectToMatch, IMatchStrategyEqual matchStrategy) throws MatchException {
297 if (matchStrategy == null){
298 matchStrategy = DefaultMatchStrategy.NewInstance(((objectToMatch).getClass()));
299 }
300 return genericDao.findMatching(objectToMatch, matchStrategy);
301 }
302
303
304
305 /* (non-Javadoc)
306 * @see eu.etaxonomy.cdm.api.service.ICommonService#findMatching(eu.etaxonomy.cdm.strategy.match.IMatchable, eu.etaxonomy.cdm.strategy.match.MatchStrategyConfigurator.MatchStrategy)
307 */
308 @Override
309 public <T extends IMatchable> List<T> findMatching(T objectToMatch, MatchStrategy strategy) throws MatchException {
310 return findMatching(objectToMatch, MatchStrategyConfigurator.getMatchStrategy(strategy));
311 }
312
313 // /* (non-Javadoc)
314 // * @see eu.etaxonomy.cdm.api.service.IService#list(java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
315 // */
316 // @Override
317 // public <TYPE extends OriginalSourceBase> Pager<TYPE> list(Class<TYPE> type,
318 // Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
319 // List<String> propertyPaths) {
320 // logger.warn("Not yet implemented");
321 // return null;
322 // }
323
324
325 @Transactional(readOnly = false)
326 @Override
327 public void saveAllMetaData(Collection<CdmMetaData> metaData) {
328 Iterator<CdmMetaData> iterator = metaData.iterator();
329 while(iterator.hasNext()){
330 CdmMetaData cdmMetaData = iterator.next();
331 genericDao.saveMetaData(cdmMetaData);
332 }
333 }
334
335 @Override
336 public Map<CdmMetaDataPropertyName, CdmMetaData> getCdmMetaData() {
337 Map<CdmMetaDataPropertyName, CdmMetaData> result = new HashMap<>();
338 List<CdmMetaData> metaDataList = genericDao.getMetaData();
339 for (CdmMetaData metaData : metaDataList){
340 CdmMetaDataPropertyName propertyName = metaData.getPropertyName();
341 result.put(propertyName, metaData);
342 }
343 return result;
344 }
345
346 @Override
347 public Object initializeCollection(UUID ownerUuid, String fieldName) {
348 return genericDao.initializeCollection(ownerUuid, fieldName);
349
350 }
351
352 @Override
353 public Object initializeCollection(UUID ownerUuid, String fieldName, List<String> propertyPaths) {
354 return genericDao.initializeCollection(ownerUuid, fieldName, propertyPaths);
355
356 }
357
358 @Override
359 public boolean isEmpty(UUID ownerUuid, String fieldName) {
360 return genericDao.isEmpty(ownerUuid, fieldName);
361
362 }
363
364 @Override
365 public int size(UUID ownerUuid, String fieldName) {
366 return genericDao.size(ownerUuid, fieldName);
367 }
368
369
370 @Override
371 public Object get(UUID ownerUuid, String fieldName, int index) {
372 return genericDao.get(ownerUuid, fieldName, index);
373 }
374
375 @Override
376 public boolean contains(UUID ownerUuid, String fieldName, Object element) {
377 return genericDao.contains(ownerUuid, fieldName, element);
378 }
379
380 @Override
381 public boolean containsKey(UUID ownerUuid, String fieldName, Object key) {
382 return genericDao.containsKey(ownerUuid, fieldName, key);
383 }
384
385 @Override
386 public boolean containsValue(UUID ownerUuid, String fieldName, Object value) {
387 return genericDao.containsValue(ownerUuid, fieldName, value);
388 }
389
390 @Override
391 @Transactional(readOnly = false)
392 public void createFullSampleData() {
393 genericDao.createFullSampleData();
394 }
395
396
397
398 @Override
399 public <S extends CdmBase> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths){
400 return genericDao.list(type, limit, start, orderHints, propertyPaths);
401 }
402
403 @Override
404 public <S extends CdmBase> long count(Class<S> type) {
405 return genericDao.count(type);
406 }
407
408 @Override
409 @Transactional(readOnly = false)
410 public CdmBase save(CdmBase newInstance) {
411 return genericDao.save(newInstance);
412 }
413
414 @Override
415 @Transactional(readOnly = false)
416 public UUID delete(CdmBase instance) {
417 return genericDao.delete(instance);
418 }
419
420 @Override
421 @Transactional(readOnly = false)
422 public UUID saveOrUpdate(CdmBase newInstance) {
423 return genericDao.saveOrUpdate(newInstance);
424 }
425
426
427 @Override
428 @Transactional(readOnly = false)
429 public <T extends CdmBase> Map<UUID,T> save(Collection<T> newInstances) {
430 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
431 //and generally the saveAll method should work for other CdmBase types with generics removed
432 return (Map<UUID, T>) originalSourceDao.saveAll((Collection)newInstances);
433 }
434
435 @Override
436 @Transactional(readOnly = false)
437 public <T extends CdmBase> Map<UUID,T> saveOrUpdate(Collection<T> newInstances) {
438 //this is very ugly, I know, but for now I do not want to copy the saveAll method from CdmEntityDaoBase to genericDao
439 //and generally the saveAll method should work for other CdmBase types with generics removed
440 return (Map<UUID, T>) originalSourceDao.saveOrUpdateAll((Collection)newInstances);
441 }
442
443
444 @Override
445 public <T extends CdmBase> boolean isMergeable(T cdmBase1, T cdmBase2, IMergeStrategy mergeStrategy) throws MergeException {
446 return genericDao.isMergeable(cdmBase1, cdmBase2, mergeStrategy);
447 }
448
449 @Override
450 public List<UUID> listUuid(Class<? extends CdmBase> clazz) {
451 return genericDao.listUuid(clazz);
452 }
453
454 }