Merge branch 'develop' of ssh://dev.e-taxonomy.eu/var/git/cdmlib into develop
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / IdentifiableServiceBase.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.ArrayList;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.apache.log4j.Logger;
22 import org.hibernate.criterion.Criterion;
23 import org.springframework.transaction.annotation.Transactional;
24
25 import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
26 import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
27 import eu.etaxonomy.cdm.api.service.dto.IdentifiedEntityDTO;
28 import eu.etaxonomy.cdm.api.service.dto.MarkedEntityDTO;
29 import eu.etaxonomy.cdm.api.service.pager.Pager;
30 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
31 import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor;
32 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
33 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
34 import eu.etaxonomy.cdm.model.common.CdmBase;
35 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
36 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
37 import eu.etaxonomy.cdm.model.common.LSID;
38 import eu.etaxonomy.cdm.model.common.MarkerType;
39 import eu.etaxonomy.cdm.model.media.Rights;
40 import eu.etaxonomy.cdm.model.reference.ISourceable;
41 import eu.etaxonomy.cdm.model.term.DefinedTerm;
42 import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao;
43 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
44 import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;
45 import eu.etaxonomy.cdm.persistence.dao.initializer.AutoPropertyInitializer;
46 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
47 import eu.etaxonomy.cdm.persistence.query.MatchMode;
48 import eu.etaxonomy.cdm.persistence.query.OrderHint;
49 import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;
50 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
51 import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
52 import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
53 import eu.etaxonomy.cdm.strategy.match.IMatchable;
54 import eu.etaxonomy.cdm.strategy.match.MatchException;
55 import eu.etaxonomy.cdm.strategy.merge.IMergable;
56 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
57 import eu.etaxonomy.cdm.strategy.merge.MergeException;
58
59 public abstract class IdentifiableServiceBase<T extends IdentifiableEntity, DAO extends IIdentifiableDao<T>> extends AnnotatableServiceBase<T,DAO>
60 implements IIdentifiableEntityService<T>{
61
62
63 protected static final int UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE = 1000;
64 protected static final Logger logger = Logger.getLogger(IdentifiableServiceBase.class);
65
66 @Override
67 @Transactional(readOnly = true)
68 public Pager<Rights> getRights(T t, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
69 long numberOfResults = dao.countRights(t);
70
71 List<Rights> results = new ArrayList<>();
72 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
73 results = dao.getRights(t, pageSize, pageNumber,propertyPaths);
74 }
75
76 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
77 }
78
79 @Override
80 @Transactional(readOnly = true)
81 public Pager<IdentifiableSource> getSources(T t, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
82 long numberOfResults = dao.countSources(t);
83
84 List<IdentifiableSource> results = new ArrayList<>();
85 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
86 results = dao.getSources(t, pageSize, pageNumber,propertyPaths);
87 }
88
89 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
90 }
91
92
93 @Transactional(readOnly = false)
94 @Override
95 public T replace(T x, T y) {
96 return dao.replace(x, y);
97 }
98
99 /*
100 * TODO - Migrated from CommonServiceBase
101 */
102 @Transactional(readOnly = true)
103 @Override
104 public ISourceable getSourcedObjectByIdInSource(Class clazz, String idInSource, String idNamespace) {
105 ISourceable<?> result = null;
106
107 List<T> list = dao.findOriginalSourceByIdInSource(idInSource, idNamespace);
108 if (! list.isEmpty()){
109 result = list.get(0);
110 }
111 return result;
112 }
113
114 @Transactional(readOnly = true)
115 @Override
116 public List<UuidAndTitleCache<T>> getUuidAndTitleCache(Integer limit, String pattern) {
117 return dao.getUuidAndTitleCache(limit, pattern);
118 }
119
120 @Transactional(readOnly = true)
121 @Override
122 public <S extends T> List<UuidAndTitleCache<S>> getUuidAndTitleCache(Class<S> clazz,Integer limit, String pattern) {
123 return dao.getUuidAndTitleCache(clazz, limit, pattern);
124 }
125
126 @Transactional(readOnly = true)
127 @Override
128 public String getTitleCache(UUID uuid, boolean refresh){
129 return dao.getTitleCache(uuid, refresh);
130 }
131
132 @Transactional(readOnly = true)
133 @Override
134 public <S extends T> Pager<S> findByTitle(Class<S> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
135 long numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);
136
137 List<S> results = new ArrayList<>();
138 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
139 results = dao.findByTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
140 }
141
142 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
143 }
144
145 @Transactional(readOnly = true)
146 @Override
147 public <S extends T> Pager<S> findByTitleWithRestrictions(Class<S> clazz, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
148 long numberOfResults = dao.countByTitleWithRestrictions(clazz, queryString, matchmode, restrictions);
149
150 List<S> results = new ArrayList<>();
151 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
152 results = dao.findByTitleWithRestrictions(clazz, queryString, matchmode, restrictions, pageSize, pageNumber, orderHints, propertyPaths);
153 }
154
155 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
156 }
157
158
159 @Transactional(readOnly = true)
160 @Override
161 public <S extends T> Pager<S> findByTitle(IIdentifiableEntityServiceConfigurator<S> config){
162
163 boolean withRestrictions = config.getRestrictions() != null && !config.getRestrictions().isEmpty();
164 boolean withCriteria = config.getCriteria() != null && !config.getCriteria().isEmpty();
165
166 if(withCriteria && withRestrictions){
167 throw new RuntimeException("Restrictions and Criteria can not be used at the same time");
168 } else if(withRestrictions){
169 return findByTitleWithRestrictions((Class<S>)config.getClazz(), config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getRestrictions(), config.getPageSize(), config.getPageNumber(), config.getOrderHints(), config.getPropertyPaths());
170 } else {
171 return findByTitle((Class<S>) config.getClazz(), config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getCriteria(), config.getPageSize(), config.getPageNumber(), config.getOrderHints(), config.getPropertyPaths());
172 }
173 }
174
175 @Transactional(readOnly = true)
176 @Override
177 public <S extends T> List<S> listByTitle(Class<S> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
178 long numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);
179
180 List<S> results = new ArrayList<>();
181 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
182 results = dao.findByTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
183 }
184 return results;
185 }
186
187 @Transactional(readOnly = true)
188 @Override
189 public <S extends T> List<S> listByTitleWithRestrictions(Class<S> clazz, String queryString,MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
190 long numberOfResults = dao.countByTitleWithRestrictions(clazz, queryString, matchmode, restrictions);
191
192 List<S> results = new ArrayList<>();
193 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
194 results = dao.findByTitleWithRestrictions(clazz, queryString, matchmode, restrictions, pageSize, pageNumber, orderHints, propertyPaths);
195 }
196 return results;
197 }
198
199 @Transactional(readOnly = true)
200 @Override
201 public Pager<String> findTitleCache(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, MatchMode matchMode){
202 long numberOfResults = dao.countTitleCache(clazz, queryString, matchMode);
203
204 List<String> results = new ArrayList<>();
205 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
206 results = dao.findTitleCache(clazz, queryString, pageSize, pageNumber, orderHints, matchMode);
207 }
208 long r = 0;
209 r += numberOfResults;
210
211 return new DefaultPagerImpl<>(pageNumber, r , pageSize, results);
212 }
213
214 @Transactional(readOnly = true)
215 @Override
216 public <S extends T> List<S> listByReferenceTitle(Class<S> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
217 long numberOfResults = dao.countByReferenceTitle(clazz, queryString, matchmode, criteria);
218
219 List<S> results = new ArrayList<>();
220 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
221 results = dao.findByReferenceTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
222 }
223 return results;
224 }
225
226 @Transactional(readOnly = true)
227 @Override
228 public <S extends T> List<S> listByReferenceTitleWithRestrictions(Class<S> clazz, String queryString,MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
229 long numberOfResults = dao.countByReferenceTitleWithRestrictions(clazz, queryString, matchmode, restrictions);
230
231 List<S> results = new ArrayList<>();
232 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
233 results = dao.findByReferenceTitleWithRestrictions(clazz, queryString, matchmode, restrictions, pageSize, pageNumber, orderHints, propertyPaths);
234 }
235 return results;
236 }
237
238 @Transactional(readOnly = true)
239 @Override
240 public T find(LSID lsid) {
241 return dao.find(lsid);
242 }
243
244 @Transactional(readOnly = true)
245 @Override
246 public Pager<T> search(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
247 // public <S extends T> Pager<S> search(Class<S> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
248 long numberOfResults = dao.count(clazz,queryString);
249
250 List<T> results = new ArrayList<>();
251 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
252 results = dao.search(clazz,queryString, pageSize, pageNumber, orderHints, propertyPaths);
253 }
254
255 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
256 }
257
258 @Override
259 @Transactional(readOnly = false)
260 public UpdateResult updateCaches() {
261 return updateCaches(null, null, null, null);
262 }
263
264 @Transactional(readOnly = false) //TODO check transactional behavior, e.g. what happens with the session if count is very large
265 protected <S extends T > UpdateResult updateCachesImpl(Class<S> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<T> cacheStrategy, IProgressMonitor subMonitor) {
266 if (stepSize == null){
267 stepSize = UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE;
268 }
269 if (subMonitor == null){
270 subMonitor = DefaultProgressMonitor.NewInstance();
271 }
272 UpdateResult result = new UpdateResult();
273 long count = dao.count(clazz);
274 long countUpdated = 0;
275
276 try {
277 subMonitor.beginTask("update titles for " + clazz.getSimpleName(), Long.valueOf(count).intValue());
278 subMonitor.setTaskName("Update " + clazz.getSimpleName());
279
280
281 //SubProgressMonitor subMonitor = monitor.("update titles for " + clazz.getSimpleName(), Long.valueOf(count).intValue());
282 int worked = 0;
283 Set<CdmEntityIdentifier> updatedCdmIds = new HashSet();
284 for(int i = 0 ; i < count ; i = i + stepSize){
285 // not sure if such strict ordering is necessary here, but for safety reasons I do it
286 ArrayList<OrderHint> orderHints = new ArrayList<>();
287 orderHints.add( new OrderHint("id", OrderHint.SortOrder.ASCENDING));
288
289
290 Map<Class<? extends CdmBase>, AutoPropertyInitializer<CdmBase>> oldAutoInit = switchOfAutoinitializer();
291 List<S> list = this.list(clazz, stepSize, i, orderHints, null);
292 switchOnOldAutoInitializer(oldAutoInit);
293
294 List<T> entitiesToUpdate = new ArrayList<>();
295 for (T entity : list){
296 entity = HibernateProxyHelper.deproxy(entity);
297 if (entity.updateCaches(cacheStrategy)){
298 countUpdated++;
299 updatedCdmIds.add(new CdmEntityIdentifier(entity.getId(), clazz));
300 }
301 worked++;
302 subMonitor.internalWorked(1);
303 }
304
305
306 if (subMonitor.isCanceled()){
307 break;
308 }
309 }
310 result.addUpdatedCdmIds(updatedCdmIds);
311 } finally {
312 subMonitor.done();
313 }
314
315 return result;
316 }
317
318 /**
319 * Brings back all auto initializers to the bean initializer
320 * @see #switchOfAutoinitializer()
321 * @param oldAutoInit
322 */
323 protected void switchOnOldAutoInitializer(
324 Map<Class<? extends CdmBase>, AutoPropertyInitializer<CdmBase>> oldAutoInit) {
325 HibernateBeanInitializer initializer = (HibernateBeanInitializer)this.appContext.getBean("defaultBeanInitializer");
326 initializer.setBeanAutoInitializers(oldAutoInit);
327 }
328
329 /**
330 * Removes all auto initializers from the bean initializer
331 *
332 * @see #switchOnOldAutoInitializer(Map)
333 * @return
334 */
335 protected Map<Class<? extends CdmBase>, AutoPropertyInitializer<CdmBase>> switchOfAutoinitializer() {
336 HibernateBeanInitializer initializer = (HibernateBeanInitializer)this.appContext.getBean("defaultBeanInitializer");
337 Map<Class<? extends CdmBase>, AutoPropertyInitializer<CdmBase>> oldAutoInitializers = initializer.getBeanAutoInitializers();
338 Map<Class<? extends CdmBase>, AutoPropertyInitializer<CdmBase>> map = new HashMap<>();
339 initializer.setBeanAutoInitializers(map);
340 return oldAutoInitializers;
341 }
342
343 private class DeduplicateState{
344 String lastTitleCache;
345 Integer pageSize = 50;
346 int nPages = 3;
347 int startPage = 0;
348 boolean isCompleted = false;
349 int result;
350 }
351
352 @Override
353 @Transactional(readOnly = false)
354 public int deduplicate(Class<? extends T> clazz, IMatchStrategyEqual matchStrategy, IMergeStrategy mergeStrategy) {
355 DeduplicateState dedupState = new DeduplicateState();
356
357 if (clazz == null){
358 logger.warn("Deduplication clazz must not be null!");
359 return 0;
360 }
361 if (! ( IMatchable.class.isAssignableFrom(clazz) && IMergable.class.isAssignableFrom(clazz) ) ){
362 logger.warn("Deduplication implemented only for classes implementing IMatchable and IMergeable. No deduplication performed!");
363 return 0;
364 }
365 Class matchableClass = clazz;
366 if (matchStrategy == null){
367 matchStrategy = DefaultMatchStrategy.NewInstance(matchableClass);
368 }
369 List<T> nextGroup = new ArrayList<>();
370
371 int result = 0;
372 // double countTotal = count(clazz);
373 //
374 // Number countPagesN = Math.ceil(countTotal/dedupState.pageSize.doubleValue()) ;
375 // int countPages = countPagesN.intValue();
376 //
377
378 List<OrderHint> orderHints = Arrays.asList(new OrderHint[]{new OrderHint("titleCache", SortOrder.ASCENDING)});
379
380 while (! dedupState.isCompleted){
381 //get x page sizes
382 List<? extends T> objectList = getPages(clazz, dedupState, orderHints);
383 //after each page check if any changes took place
384 int nUnEqualPages = handleAllPages(objectList, dedupState, nextGroup, matchStrategy, mergeStrategy);
385 nUnEqualPages = nUnEqualPages + dedupState.pageSize * dedupState.startPage;
386 //refresh start page counter
387 int finishedPages = nUnEqualPages / dedupState.pageSize;
388 dedupState.startPage = finishedPages;
389 }
390
391 result += handleLastGroup(nextGroup, matchStrategy, mergeStrategy);
392 return result;
393 }
394
395
396 private int handleAllPages(List<? extends T> objectList, DeduplicateState dedupState, List<T> nextGroup, IMatchStrategyEqual matchStrategy, IMergeStrategy mergeStrategy) {
397 int nUnEqual = 0;
398 for (T object : objectList){
399 String currentTitleCache = object.getTitleCache();
400 if (currentTitleCache != null && currentTitleCache.equals(dedupState.lastTitleCache)){
401 //=titleCache
402 nextGroup.add(object);
403 }else{
404 //<> titleCache
405 dedupState.result += handleLastGroup(nextGroup, matchStrategy, mergeStrategy);
406 nextGroup = new ArrayList<>();
407 nextGroup.add(object);
408 nUnEqual++;
409 }
410 dedupState.lastTitleCache = currentTitleCache;
411 }
412 handleLastGroup(nextGroup, matchStrategy, mergeStrategy);
413 return nUnEqual;
414 }
415
416 private <S extends T> List<S> getPages(Class<S> clazz, DeduplicateState dedupState, List<OrderHint> orderHints) {
417 List<S> result = new ArrayList<>();
418 for (int pageNo = dedupState.startPage; pageNo < dedupState.startPage + dedupState.nPages; pageNo++){
419 List<S> objectList = listByTitleWithRestrictions(clazz, null, null, null, dedupState.pageSize, pageNo, orderHints, null);
420 result.addAll(objectList);
421 }
422 if (result.size()< dedupState.nPages * dedupState.pageSize ){
423 dedupState.isCompleted = true;
424 }
425 return result;
426 }
427
428 private int handleLastGroup(List<T> group, IMatchStrategyEqual matchStrategy, IMergeStrategy mergeStrategy) {
429 int result = 0;
430 int size = group.size();
431 Set<Integer> exclude = new HashSet<>(); //set to collect all objects, that have been merged already
432 for (int i = 0; i < size - 1; i++){
433 if (exclude.contains(i)){
434 continue;
435 }
436 for (int j = i + 1; j < size; j++){
437 if (exclude.contains(j)){
438 continue;
439 }
440 T firstObject = group.get(i);
441 T secondObject = group.get(j);
442
443 try {
444 if (matchStrategy.invoke((IMatchable)firstObject, (IMatchable)secondObject).isSuccessful()){
445 commonService.merge((IMergable)firstObject, (IMergable)secondObject, mergeStrategy);
446 exclude.add(j);
447 result++;
448 }
449 } catch (MatchException e) {
450 logger.warn("MatchException when trying to match " + firstObject.getTitleCache());
451 e.printStackTrace();
452 } catch (MergeException e) {
453 logger.warn("MergeException when trying to merge " + firstObject.getTitleCache());
454 e.printStackTrace();
455 }
456 }
457 }
458 return result;
459 }
460
461 @Transactional(readOnly = true)
462 @Override
463 public long countByTitle(Class<? extends T> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria){
464 long numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);
465
466 return numberOfResults;
467 }
468
469 @Transactional(readOnly = true)
470 @Override
471 public long countByTitleWithRestrictions(Class<? extends T> clazz, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions){
472 long numberOfResults = dao.countByTitleWithRestrictions(clazz, queryString, matchmode, restrictions);
473
474 return numberOfResults;
475 }
476
477 @Transactional(readOnly = true)
478 @Override
479 public long countByTitle(IIdentifiableEntityServiceConfigurator<T> config){
480
481 boolean withRestrictions = config.getRestrictions() != null && !config.getRestrictions().isEmpty();
482 boolean withCriteria = config.getCriteria() != null && !config.getCriteria().isEmpty();
483
484 if(withCriteria && withRestrictions){
485 throw new RuntimeException("Restrictions and Criteria can not be used at the same time");
486 } else if(withRestrictions){
487 return countByTitleWithRestrictions(config.getClazz(), config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getRestrictions());
488 } else {
489 return countByTitle(config.getClazz(), config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getCriteria());
490 }
491
492 }
493
494 @Override
495 @Transactional(readOnly = true)
496 public <S extends T> Pager<IdentifiedEntityDTO<S>> findByIdentifier(
497 Class<S> clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode,
498 boolean includeEntity, Integer pageSize,
499 Integer pageNumber, List<String> propertyPaths) {
500
501 long numberOfResults = dao.countByIdentifier(clazz, identifier, identifierType, matchmode);
502 List<Object[]> daoResults = new ArrayList<>();
503 if(numberOfResults > 0) { // no point checking again
504 daoResults = dao.findByIdentifier(clazz, identifier, identifierType,
505 matchmode, includeEntity, pageSize, pageNumber, propertyPaths);
506 }
507
508 List<IdentifiedEntityDTO<S>> result = new ArrayList<>();
509 for (Object[] daoObj : daoResults){
510 if (includeEntity){
511 result.add(new IdentifiedEntityDTO<>((DefinedTerm)daoObj[0], (String)daoObj[1], (S)daoObj[2]));
512 }else{
513 result.add(new IdentifiedEntityDTO<>((DefinedTerm)daoObj[0], (String)daoObj[1], (UUID)daoObj[2], (String)daoObj[3], null));
514 }
515 }
516 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, result);
517 }
518
519 @Override
520 @Transactional(readOnly = true)
521 public <S extends T> List<IdentifiedEntityDTO<S>> listByIdentifier(
522 Class<S> clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode,
523 boolean includeEntity, List<String> propertyPaths, Integer limit) {
524
525 long numberOfResults = dao.countByIdentifier(clazz, identifier, identifierType, matchmode);
526 List<Object[]> daoResults = new ArrayList<>();
527 if(numberOfResults > 0) { // no point checking again
528 daoResults = dao.findByIdentifier(clazz, identifier, identifierType,
529 matchmode, includeEntity, limit, 0, propertyPaths);
530 }
531
532 List<IdentifiedEntityDTO<S>> result = new ArrayList<>();
533 for (Object[] daoObj : daoResults){
534 if (includeEntity){
535 result.add(new IdentifiedEntityDTO<>((DefinedTerm)daoObj[0], (String)daoObj[1], (S)daoObj[2]));
536 }else{
537 result.add(new IdentifiedEntityDTO<>((DefinedTerm)daoObj[0], (String)daoObj[1], (UUID)daoObj[2], (String)daoObj[3], null));
538 }
539 }
540 return result;
541 }
542
543
544 @Override
545 @Transactional(readOnly = true)
546 public <S extends T> Pager<MarkedEntityDTO<S>> findByMarker(
547 Class<S> clazz, MarkerType markerType, Boolean markerValue,
548 boolean includeEntity, Integer pageSize,
549 Integer pageNumber, List<String> propertyPaths) {
550
551 Long numberOfResults = dao.countByMarker(clazz, markerType, markerValue);
552 List<Object[]> daoResults = new ArrayList<>();
553 if(numberOfResults > 0) { // no point checking again
554 daoResults = dao.findByMarker(clazz, markerType, markerValue, includeEntity,
555 pageSize, pageNumber, propertyPaths);
556 }
557
558 List<MarkedEntityDTO<S>> result = new ArrayList<>();
559 for (Object[] daoObj : daoResults){
560 if (includeEntity){
561 result.add(new MarkedEntityDTO<>((MarkerType)daoObj[0], (Boolean)daoObj[1], (S)daoObj[2]));
562 }else{
563 result.add(new MarkedEntityDTO<>((MarkerType)daoObj[0], (Boolean)daoObj[1], (UUID)daoObj[2], (String)daoObj[3]));
564 }
565 }
566 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, result);
567 }
568
569 @Override
570 @Transactional(readOnly = true)
571 public List<UuidAndTitleCache<T>> findUuidAndTitleCacheByMarker(Integer limit, String pattern,
572 MarkerType markerType){
573
574 Long numberOfResults = dao.countByMarker(null, markerType, null);
575 List<UuidAndTitleCache<T>> daoResults = new ArrayList<>();
576 if(numberOfResults > 0) { // no point checking again
577 daoResults = dao.getUuidAndTitleCacheByMarker(limit, pattern, markerType);
578 }
579
580
581 return daoResults;
582 }
583
584
585
586 }
587