cleanup
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonNodeServiceImpl.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.Collection;
15 import java.util.Collections;
16 import java.util.Comparator;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map.Entry;
21 import java.util.Set;
22 import java.util.UUID;
23
24 import org.apache.log4j.Logger;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.security.core.Authentication;
27 import org.springframework.stereotype.Service;
28 import org.springframework.transaction.annotation.Transactional;
29 import org.springframework.transaction.interceptor.TransactionAspectSupport;
30
31 import eu.etaxonomy.cdm.api.service.UpdateResult.Status;
32 import eu.etaxonomy.cdm.api.service.config.NodeDeletionConfigurator.ChildHandling;
33 import eu.etaxonomy.cdm.api.service.config.PublishForSubtreeConfigurator;
34 import eu.etaxonomy.cdm.api.service.config.SecundumForSubtreeConfigurator;
35 import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
36 import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;
37 import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
38 import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTO;
39 import eu.etaxonomy.cdm.api.service.pager.Pager;
40 import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
41 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
42 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
43 import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor;
44 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
45 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
46 import eu.etaxonomy.cdm.hibernate.HHH_9751_Util;
47 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
48 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
49 import eu.etaxonomy.cdm.model.common.CdmBase;
50 import eu.etaxonomy.cdm.model.common.Language;
51 import eu.etaxonomy.cdm.model.common.LanguageString;
52 import eu.etaxonomy.cdm.model.common.TreeIndex;
53 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
54 import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
55 import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
56 import eu.etaxonomy.cdm.model.description.TaxonDescription;
57 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
58 import eu.etaxonomy.cdm.model.name.HybridRelationship;
59 import eu.etaxonomy.cdm.model.name.Rank;
60 import eu.etaxonomy.cdm.model.name.TaxonName;
61 import eu.etaxonomy.cdm.model.permission.Operation;
62 import eu.etaxonomy.cdm.model.reference.Reference;
63 import eu.etaxonomy.cdm.model.taxon.Classification;
64 import eu.etaxonomy.cdm.model.taxon.HomotypicGroupTaxonComparator;
65 import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
66 import eu.etaxonomy.cdm.model.taxon.Synonym;
67 import eu.etaxonomy.cdm.model.taxon.SynonymType;
68 import eu.etaxonomy.cdm.model.taxon.Taxon;
69 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
70 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
71 import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
72 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
73 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
74 import eu.etaxonomy.cdm.model.term.DefinedTerm;
75 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
76 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
77 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
78 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeFilterDao;
79 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
80 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
81 import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
82 import eu.etaxonomy.cdm.persistence.query.OrderHint;
83
84 /**
85 * @author n.hoffmann
86 * @since Apr 9, 2010
87 */
88 @Service
89 @Transactional(readOnly = true)
90 public class TaxonNodeServiceImpl
91 extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao>
92 implements ITaxonNodeService{
93 private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
94
95 @Autowired
96 private IBeanInitializer defaultBeanInitializer;
97
98 @Autowired
99 private ITaxonService taxonService;
100
101 @Autowired
102 private IReferenceService referenceService;
103
104 @Autowired
105 private IDescriptiveDataSetService dataSetService;
106
107 @Autowired
108 private IAgentService agentService;
109
110 @Autowired
111 private INameService nameService;
112
113 @Autowired
114 private IReferenceService refService;
115
116 @Autowired
117 private ITaxonNodeFilterDao nodeFilterDao;
118
119 @Autowired
120 IProgressMonitorService progressMonitorService;
121
122 @Autowired
123 private ICdmPermissionEvaluator permissionEvaluator;
124
125 @Override
126 public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
127 List<String> propertyPaths, boolean recursive, boolean includeUnpublished,
128 NodeSortMode sortMode) {
129
130 getSession().refresh(taxonNode);
131 List<TaxonNode> childNodes;
132 if (recursive == true){
133 childNodes = dao.listChildrenOf(taxonNode, null, null, recursive, includeUnpublished, null);
134 }else if (includeUnpublished){
135 childNodes = new ArrayList<>(taxonNode.getChildNodes());
136 }else{
137 childNodes = new ArrayList<>();
138 for (TaxonNode node:taxonNode.getChildNodes()){
139 if (node.getTaxon().isPublish()){
140 childNodes.add(node);
141 }
142 }
143 }
144
145 HHH_9751_Util.removeAllNull(childNodes);
146
147 if (sortMode != null){
148 Comparator<TaxonNode> comparator = sortMode.newComparator();
149 Collections.sort(childNodes, comparator);
150 }
151 defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
152 return childNodes;
153 }
154
155 @Override
156 public List<TaxonNode> listChildrenOf(TaxonNode node, Integer pageSize, Integer pageIndex,
157 boolean recursive, boolean includeUnpublished, List<String> propertyPaths){
158 return dao.listChildrenOf(node, pageSize, pageIndex, recursive, includeUnpublished, propertyPaths);
159 }
160
161 @Override
162 public TaxonNodeDto getParentUuidAndTitleCache(ITaxonTreeNode child) {
163 UUID uuid = child.getUuid();
164 int id = child.getId();
165 TaxonNodeDto uuidAndTitleCache = new TaxonNodeDto(uuid, id, null);
166 return getParentUuidAndTitleCache(uuidAndTitleCache);
167 }
168
169 @Override
170 public TaxonNodeDto getParentUuidAndTitleCache(TaxonNodeDto child) {
171 return dao.getParentUuidAndTitleCache(child);
172 }
173
174 @Override
175 public List<TaxonNodeDto> listChildNodesAsTaxonNodeDto(TaxonNodeDto parent) {
176 return dao.listChildNodesAsTaxonNodeDto(parent);
177 }
178
179 @Override
180 public List<UuidAndTitleCache<TaxonNode>> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
181 return dao.getUuidAndTitleCache(limit, pattern, classificationUuid);
182 }
183
184 @Override
185 public List<TaxonNodeDto> listChildNodesAsTaxonNodeDto(ITaxonTreeNode parent) {
186 TaxonNodeDto uuidAndTitleCache = new TaxonNodeDto(parent);
187 return listChildNodesAsTaxonNodeDto(uuidAndTitleCache);
188 }
189
190 @Override
191 public List<TaxonNodeDto> taxonNodeDtoParentRank(Classification classification, Rank rank, TaxonName name) {
192 return dao.getParentTaxonNodeDtoForRank(classification, rank, name);
193 }
194
195 @Override
196 public List<TaxonNodeDto> taxonNodeDtoParentRank(Classification classification, Rank rank, TaxonBase<?> taxonBase) {
197 return dao.getParentTaxonNodeDtoForRank(classification, rank, taxonBase);
198 }
199
200 @Override
201 public Pager<TaxonNodeDto> pageChildNodesDTOs(UUID taxonNodeUuid, boolean recursive, boolean includeUnpublished,
202 boolean doSynonyms, NodeSortMode sortMode,
203 Integer pageSize, Integer pageIndex) {
204
205 TaxonNode parentNode = dao.load(taxonNodeUuid);
206
207 List<CdmBase> allRecords = new ArrayList<>();
208
209 //acceptedTaxa
210 List<TaxonNode> childNodes = loadChildNodesOfTaxonNode(parentNode, null, recursive, includeUnpublished, sortMode);
211 allRecords.addAll(childNodes);
212
213 //add synonyms if pager is not yet full synonyms
214 if (doSynonyms){
215 List<Synonym> synList = new ArrayList<>(parentNode.getTaxon().getSynonyms());
216 Collections.sort(synList, new HomotypicGroupTaxonComparator(null));
217 //TODO: test sorting
218
219 allRecords.addAll(synList);
220 }
221
222 List<TaxonNodeDto> dtos = new ArrayList<>(pageSize==null?25:pageSize);
223 long totalCount = Long.valueOf(allRecords.size());
224
225 TaxonName parentName = null;
226
227 for(CdmBase record : PagerUtils.pageList(allRecords, pageIndex, pageSize)) {
228 if (record.isInstanceOf(TaxonNode.class)){
229 dtos.add(new TaxonNodeDto(CdmBase.deproxy(record, TaxonNode.class)));
230 }else if (record.isInstanceOf(Synonym.class)){
231 Synonym synonym = CdmBase.deproxy(record, Synonym.class);
232 parentName = parentName == null? parentNode.getTaxon().getName(): parentName;
233 boolean isHomotypic = synonym.getName().isHomotypic(parentName);
234 dtos.add(new TaxonNodeDto(synonym, isHomotypic));
235 }
236 }
237 return new DefaultPagerImpl<>(pageIndex, totalCount, pageSize , dtos);
238 }
239
240 @Override
241 public TaxonNodeDto parentDto(UUID taxonNodeUuid) {
242 TaxonNode taxonNode = dao.load(taxonNodeUuid);
243 if(taxonNode.getParent() != null) {
244 return new TaxonNodeDto(taxonNode.getParent());
245 }
246 return null;
247 }
248
249 @Override
250 public TaxonNodeDto dto(UUID taxonNodeUuid) {
251 TaxonNode taxonNode = dao.load(taxonNodeUuid);
252 if (taxonNode != null){
253 return new TaxonNodeDto(taxonNode);
254 }
255 return null;
256 }
257
258 @Override
259 @Autowired
260 protected void setDao(ITaxonNodeDao dao) {
261 this.dao = dao;
262 }
263
264 @Override
265 @Transactional(readOnly = false)
266 public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode,
267 SynonymType synonymType, Reference citation, String citationMicroReference, boolean setNameInSource) {
268
269 // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
270 // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
271 if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){
272 throw new IllegalArgumentException("A mandatory parameter was null.");
273 }
274
275 if(oldTaxonNode.equals(newAcceptedTaxonNode)){
276 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
277 }
278
279 Classification classification = oldTaxonNode.getClassification();
280 Taxon oldTaxon = HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
281 Taxon newAcceptedTaxon = (Taxon)this.taxonService.find(newAcceptedTaxonNode.getTaxon().getUuid());
282 newAcceptedTaxon = HibernateProxyHelper.deproxy(newAcceptedTaxon);
283 // Move oldTaxon to newTaxon
284 //TaxonName synonymName = oldTaxon.getName();
285 TaxonName newSynonymName = CdmBase.deproxy(oldTaxon.getName());
286 HomotypicalGroup group = CdmBase.deproxy(newSynonymName.getHomotypicalGroup());
287 if (synonymType == null){
288 if (newSynonymName.isHomotypic(newAcceptedTaxon.getName())){
289 synonymType = SynonymType.HOMOTYPIC_SYNONYM_OF();
290 }else{
291 synonymType = SynonymType.HETEROTYPIC_SYNONYM_OF();
292 }
293 }
294
295 //set homotypic group
296 TaxonName newAcceptedTaxonName = HibernateProxyHelper.deproxy(newAcceptedTaxon.getName(), TaxonName.class);
297 newAcceptedTaxon.setName(newAcceptedTaxonName);
298 // Move Synonym Relations to new Taxon
299 newAcceptedTaxon.addSynonymName(newSynonymName, citation, citationMicroReference, synonymType);
300 // Move Synonyms to new Taxon
301 // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
302 List<Synonym> synonymsInHomotypicalGroup = null;
303
304 //the synonyms of the homotypical group of the old taxon
305 if (synonymType.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())){
306 synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
307 }
308
309 Set<Synonym> syns = new HashSet<>(oldTaxon.getSynonyms());
310 for(Synonym synonym : syns){
311 SynonymType srt;
312 if(synonym.getHomotypicGroup()!= null
313 && synonym.getHomotypicGroup().equals(newAcceptedTaxonName.getHomotypicalGroup())) {
314 srt = SynonymType.HOMOTYPIC_SYNONYM_OF();
315 } else if(synonym.getType() != null && synonym.getType().equals(SynonymType.HOMOTYPIC_SYNONYM_OF())) {
316 if (synonymType.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())){
317 srt = SynonymType.HOMOTYPIC_SYNONYM_OF();
318 } else{
319 srt = SynonymType.HETEROTYPIC_SYNONYM_OF();
320 }
321 } else {
322 if (synonymsInHomotypicalGroup != null && synonymsInHomotypicalGroup.contains(synonym)){
323 srt = SynonymType.HOMOTYPIC_SYNONYM_OF();
324 }else{
325 srt = synonym.getType();
326 }
327
328 }
329
330 newAcceptedTaxon.addSynonym(synonym, srt);
331
332
333 /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymType.HETEROTYPIC_SYNONYM_OF())){
334 homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
335 }*/
336
337 }
338
339
340 // CHILD NODES
341 if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
342 List<TaxonNode> childNodes = new ArrayList<>();
343 for (TaxonNode childNode : oldTaxonNode.getChildNodes()){
344 childNodes.add(childNode);
345 }
346 for(TaxonNode childNode :childNodes){
347 newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
348 }
349 }
350
351 //Move Taxon RelationShips to new Taxon
352 for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
353 Taxon fromTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
354 Taxon toTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
355 if (fromTaxon == oldTaxon){
356 newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),
357 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
358
359 }else if(toTaxon == oldTaxon){
360 fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
361 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
362 taxonService.saveOrUpdate(fromTaxon);
363
364 }else{
365 logger.warn("Taxon is not part of its own Taxonrelationship");
366 }
367 // Remove old relationships
368
369 fromTaxon.removeTaxonRelation(taxonRelationship);
370 toTaxon.removeTaxonRelation(taxonRelationship);
371 taxonRelationship.setToTaxon(null);
372 taxonRelationship.setFromTaxon(null);
373 }
374
375 //Move descriptions to new taxon
376 List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
377 for(TaxonDescription description : descriptions){
378 String message = "Description copied from former accepted taxon: %s (Old title: %s)";
379 message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());
380 description.setTitleCache(message, true);
381 if (setNameInSource) {
382 for (DescriptionElementBase element: description.getElements()){
383 for (DescriptionElementSource source: element.getSources()){
384 if (source.getNameUsedInSource() == null){
385 source.setNameUsedInSource(newSynonymName);
386 }
387 }
388 }
389 }
390 //oldTaxon.removeDescription(description, false);
391 newAcceptedTaxon.addDescription(description);
392 }
393 oldTaxon.clearDescriptions();
394
395 taxonService.saveOrUpdate(newAcceptedTaxon);
396
397 taxonService.saveOrUpdate(oldTaxon);
398 taxonService.getSession().flush();
399
400 TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
401 conf.setDeleteSynonymsIfPossible(false);
402 conf.setDeleteNameIfPossible(false);
403 DeleteResult result = taxonService.isDeletable(oldTaxon.getUuid(), conf);
404
405
406 if (result.isOk()){
407 result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());
408
409 }else{
410 result.setStatus(Status.OK);
411 TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
412 config.setDeleteElement(false);
413 conf.setTaxonNodeConfig(config);
414 result.includeResult(deleteTaxonNode(oldTaxonNode, conf));
415 }
416
417 result.addUpdatedObject(newAcceptedTaxon);
418
419
420 //oldTaxonNode.delete();
421 return result;
422 }
423 @Override
424 @Transactional(readOnly = false)
425 public UpdateResult makeTaxonNodeSynonymsOfAnotherTaxonNode( Set<UUID> oldTaxonNodeUuids,
426 UUID newAcceptedTaxonNodeUUIDs,
427 SynonymType synonymType,
428 Reference citation,
429 String citationMicroReference,
430 boolean setNameInSource) {
431 UpdateResult result = new UpdateResult();
432 for (UUID nodeUuid: oldTaxonNodeUuids) {
433 result.includeResult(makeTaxonNodeASynonymOfAnotherTaxonNode(nodeUuid, newAcceptedTaxonNodeUUIDs, synonymType, citation, citationMicroReference, setNameInSource));
434 }
435 return result;
436 }
437
438 @Override
439 @Transactional(readOnly = false)
440 public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,
441 UUID newAcceptedTaxonNodeUUID,
442 SynonymType synonymType,
443 Reference citation,
444 String citationMicroReference,
445 boolean setNameInSource) {
446
447 TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
448 TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
449 TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);
450
451 UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,
452 newTaxonNode,
453 synonymType,
454 citation,
455 citationMicroReference, setNameInSource);
456 result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
457 result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
458 result.setCdmEntity(oldTaxonParentNode);
459 return result;
460 }
461
462 @Override
463 @Transactional(readOnly = false)
464 public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {
465
466 if (config == null){
467 config = new TaxonDeletionConfigurator();
468 }
469 DeleteResult result = new DeleteResult();
470 Classification classification = null;
471 List<TaxonNode> taxonNodes = new ArrayList<>(list);
472
473 for (TaxonNode treeNode:taxonNodes){
474 if (treeNode != null){
475
476 TaxonNode taxonNode;
477 taxonNode = CdmBase.deproxy(treeNode);
478 TaxonNode parent = taxonNode.getParent();
479 //check whether the node has children or the children are already deleted
480 if(taxonNode.hasChildNodes()) {
481 List<TaxonNode> children = new ArrayList<> ();
482 List<TaxonNode> childNodesList = taxonNode.getChildNodes();
483 children.addAll(childNodesList);
484 //To avoid NPE when child is also in list of taxonNodes, remove it from the list
485 Iterator<TaxonNode> it = taxonNodes.iterator();
486 for (TaxonNode child: children) {
487 while (it.hasNext()) {
488 if (it.next().equals(child)) {
489 it.remove();
490 }
491 }
492 }
493 int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);
494 boolean childHandling = (compare == 0)? true: false;
495 if (childHandling){
496 boolean changeDeleteTaxon = false;
497 if (!config.getTaxonNodeConfig().isDeleteTaxon()){
498 config.getTaxonNodeConfig().setDeleteTaxon(true);
499 changeDeleteTaxon = true;
500 }
501 DeleteResult resultNodes = deleteTaxonNodes(children, config);
502 if (!resultNodes.isOk()){
503 result.addExceptions(resultNodes.getExceptions());
504 result.setStatus(resultNodes.getStatus());
505 }
506 if (changeDeleteTaxon){
507 config.getTaxonNodeConfig().setDeleteTaxon(false);
508 }
509
510 } else {
511 //move the children to the parent
512
513 for (TaxonNode child: childNodesList){
514 parent.addChildNode(child, child.getReference(), child.getMicroReference());
515 }
516
517 }
518 }
519
520 classification = taxonNode.getClassification();
521
522 if (classification.getRootNode().equals(taxonNode)){
523 classification.removeRootNode();
524 classification = null;
525 }else if (classification.getChildNodes().contains(taxonNode)){
526 Taxon taxon = taxonNode.getTaxon();
527 classification.deleteChildNode(taxonNode);
528
529 //node is rootNode
530 if (taxon != null){
531
532 if (config.getTaxonNodeConfig().isDeleteTaxon()){
533 taxonService.saveOrUpdate(taxon);
534 saveOrUpdate(taxonNode);
535
536 TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
537 configNew.setClassificationUuid(classification.getUuid());
538 DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
539 if (!resultTaxon.isOk()){
540 result.addExceptions(resultTaxon.getExceptions());
541 result.setStatus(resultTaxon.getStatus());
542 }
543
544 }
545 }
546 classification = null;
547
548 } else {
549 //classification = null;
550 Taxon taxon = taxonNode.getTaxon();
551 taxon = CdmBase.deproxy(taxon);
552 if (taxon != null){
553 taxon.removeTaxonNode(taxonNode);
554 if (config.getTaxonNodeConfig().isDeleteTaxon()){
555 TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
556 saveOrUpdate(taxonNode);
557 taxonService.saveOrUpdate(taxon);
558 DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
559
560 if (!resultTaxon.isOk()){
561 result.addExceptions(resultTaxon.getExceptions());
562 result.setStatus(resultTaxon.getStatus());
563 }
564 }
565 }
566
567 }
568
569 result.addUpdatedObject(parent);
570 if(result.getCdmEntity() == null){
571 result.setCdmEntity(taxonNode);
572 }
573 UUID uuid = dao.delete(taxonNode);
574 logger.debug("Deleted node " +uuid.toString());
575
576 }
577 }
578 /*if (classification != null){
579 result.addUpdatedObject(classification);
580 DeleteResult resultClassification = classService.delete(classification);
581 if (!resultClassification.isOk()){
582 result.addExceptions(resultClassification.getExceptions());
583 result.setStatus(resultClassification.getStatus());
584 }
585 }*/
586 return result;
587 }
588
589
590 @Override
591 @Transactional(readOnly = false)
592 public DeleteResult deleteTaxonNodes(Collection<UUID> nodeUuids, TaxonDeletionConfigurator config) {
593 List<TaxonNode> nodes = new ArrayList<>();
594 for(UUID nodeUuid : nodeUuids) {
595 nodes.add(dao.load(nodeUuid));
596 }
597 return deleteTaxonNodes(nodes, config);
598 }
599
600
601 @Override
602 @Transactional(readOnly = false)
603 public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
604
605 TaxonNode node = CdmBase.deproxy(dao.load(nodeUUID));
606 return deleteTaxonNode(node, config);
607 }
608
609 @Override
610 @Transactional(readOnly = false)
611 public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
612 DeleteResult result = new DeleteResult();
613 if (node == null){
614 result.setAbort();
615 result.addException(new Exception("The TaxonNode was already deleted."));
616 return result;
617 }
618 Taxon taxon = null;
619 try{
620 taxon = HibernateProxyHelper.deproxy(node.getTaxon());
621 }catch(NullPointerException e){
622 result.setAbort();
623 result.addException(new Exception("The Taxon was already deleted."));
624
625 }
626
627
628 TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);
629 if (config == null){
630 config = new TaxonDeletionConfigurator();
631 }
632
633
634 if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.MOVE_TO_PARENT)){
635 Object[] children = node.getChildNodes().toArray();
636 TaxonNode childNode;
637 for (Object child: children){
638 childNode = (TaxonNode) child;
639 parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());
640
641 }
642 }else{
643 result.includeResult(deleteTaxonNodes(node.getChildNodes(), config));
644 }
645
646 //remove node from DescriptiveDataSet
647 commonService.getReferencingObjects(node).stream()
648 .filter(obj->obj instanceof DescriptiveDataSet)
649 .forEach(dataSet->{
650 ((DescriptiveDataSet)dataSet).removeTaxonSubtree(node);
651 dataSetService.saveOrUpdate((DescriptiveDataSet) dataSet);
652 });
653
654 if (taxon != null){
655 if (config.getTaxonNodeConfig().isDeleteTaxon() && (config.isDeleteInAllClassifications() || taxon.getTaxonNodes().size() == 1)){
656 result = taxonService.deleteTaxon(taxon.getUuid(), config, node.getClassification().getUuid());
657 result.addUpdatedObject(parent);
658 if (result.isOk()){
659 return result;
660 }
661 } else {
662 result.addUpdatedObject(taxon);
663 }
664 }
665 result.setCdmEntity(node);
666 boolean success = true;
667 if (taxon != null){
668 success = taxon.removeTaxonNode(node);
669 taxonService.saveOrUpdate(taxon);
670 }
671 dao.saveOrUpdate(parent);
672
673 result.addUpdatedObject(parent);
674
675 if (success){
676 result.setStatus(Status.OK);
677 if (parent != null){
678 parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);
679 int index = parent.getChildNodes().indexOf(node);
680 if (index > -1){
681 parent.removeChild(index);
682 }
683 }
684 if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)).equals(null)){
685 result.getUpdatedObjects().remove(node);
686 result.addDeletedObject(node);
687 return result;
688 } else {
689 result.setError();
690 return result;
691 }
692 }else{
693 if (dao.findByUuid(node.getUuid()) != null){
694 result.setError();
695 result.addException(new Exception("The node can not be removed from the taxon."));
696 }
697 return result;
698 }
699 }
700
701
702 @Override
703 public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
704 return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
705 }
706
707 @Override
708 public int countAllNodesForClassification(Classification classification) {
709 return dao.countTaxonOfAcceptedTaxaByClassification(classification);
710 }
711
712 @Override
713 @Transactional
714 public UpdateResult moveTaxonNode(UUID taxonNodeUuid, UUID targetNodeUuid, int movingType){
715 TaxonNode taxonNode = HibernateProxyHelper.deproxy(dao.load(taxonNodeUuid));
716 TaxonNode targetNode = HibernateProxyHelper.deproxy(dao.load(targetNodeUuid));
717 UpdateResult result = moveTaxonNode(taxonNode, targetNode, movingType);
718 return result;
719 }
720
721 @Override
722 @Transactional
723 public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, int movingType){
724 UpdateResult result = new UpdateResult();
725
726 TaxonNode parentParent = HibernateProxyHelper.deproxy(newParent.getParent());
727 Integer sortIndex = -1;
728 if (movingType == 0){
729 sortIndex = 0;
730 }else if (movingType == 1){
731 sortIndex = newParent.getSortIndex();
732 newParent = parentParent;
733 } else if (movingType == 2){
734 sortIndex = newParent.getSortIndex() +1;
735 newParent = parentParent;
736 } else{
737 result.setAbort();
738 result.addException(new Exception("The moving type "+ movingType +" is not supported."));
739 }
740
741 taxonNode = newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(), taxonNode.getMicroReference());
742 result.addUpdatedObject(taxonNode);
743
744 return result;
745 }
746
747 @Override
748 @Transactional
749 public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, int movingType, IProgressMonitor monitor){
750
751 if (monitor == null){
752 monitor = DefaultProgressMonitor.NewInstance();
753 }
754 UpdateResult result = new UpdateResult();
755
756 TaxonNode targetNode = dao.load(newParentNodeUuid);
757 List<TaxonNode> nodes = dao.list(taxonNodeUuids, null, null, null, null);
758
759 monitor.beginTask("Move Taxonnodes", nodes.size()*2);
760 monitor.subTask("move taxon nodes");
761 for (TaxonNode node: nodes){
762 if (!monitor.isCanceled()){
763 if (!nodes.contains(node.getParent())){
764 result.includeResult(moveTaxonNode(node,targetNode, movingType));
765 }
766 monitor.worked(1);
767 }else{
768 monitor.done();
769 result.setAbort();
770 break;
771 }
772 }
773 if (!monitor.isCanceled()){
774 monitor.subTask("saving and reindex");
775 dao.saveOrUpdateAll(nodes);
776 }else{
777 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
778 }
779
780 monitor.done();
781 return result;
782 }
783
784 @Override
785 public Pager<TaxonNodeAgentRelation> pageTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
786 UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
787
788
789 List<TaxonNodeAgentRelation> records = null;
790
791 long count = dao.countTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid);
792 if(PagerUtils.hasResultsInRange(count, pageIndex, pageSize)) {
793 records = dao.listTaxonNodeAgentRelations(taxonUuid, classificationUuid,
794 agentUuid, rankUuid, relTypeUuid, PagerUtils.startFor(pageSize, pageIndex), PagerUtils.limitFor(pageSize), propertyPaths);
795 }
796
797 Pager<TaxonNodeAgentRelation> pager = new DefaultPagerImpl<>(pageIndex, count, pageSize, records);
798 return pager;
799 }
800
801 @Override
802 @Transactional
803 public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){
804 UpdateResult result = new UpdateResult();
805 if (newTaxon.getName().getId() != 0){
806 TaxonName name = nameService.load(newTaxon.getName().getUuid());
807 newTaxon.setName(name);
808 }else{
809 for (HybridRelationship rel : newTaxon.getName().getHybridChildRelations()){
810 if (!rel.getHybridName().isPersited()) {
811 nameService.save(rel.getHybridName());
812 }
813 if (!rel.getParentName().isPersited()) {
814 nameService.save(rel.getParentName());
815 }
816 }
817 }
818 UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
819 newTaxon = (Taxon) taxonService.load(taxonUUID);
820
821 TaxonNode parent = dao.load(parentNodeUuid);
822 TaxonNode child = null;
823 try{
824 child = parent.addChildTaxon(newTaxon,ref, microref);
825 }catch(Exception e){
826 result.addException(e);
827 result.setError();
828 return result;
829 }
830 child = dao.save(child);
831
832 result.addUpdatedObject(parent);
833 if (child != null){
834 result.setCdmEntity(child);
835 }
836 return result;
837
838 }
839
840
841 @Override
842 @Transactional
843 public UpdateResult saveNewTaxonNode(TaxonNode newTaxonNode){
844 UpdateResult result = new UpdateResult();
845 UUID parentUuid = newTaxonNode.getParent().getUuid();
846 Taxon taxon = null;
847
848 if (newTaxonNode.getTaxon().getId() != 0){
849 taxon = (Taxon)taxonService.load(newTaxonNode.getTaxon().getUuid());
850 //newTaxonNode.setTaxon(taxon);
851 }else if (newTaxonNode.getTaxon().getName().getId() != 0){
852 TaxonName name = nameService.load(newTaxonNode.getTaxon().getName().getUuid());
853 taxon = newTaxonNode.getTaxon();
854 taxon.setName(name);
855 }else{
856 for (HybridRelationship rel : newTaxonNode.getTaxon().getName().getHybridChildRelations()){
857 if (!rel.getHybridName().isPersited()) {
858 nameService.save(rel.getHybridName());
859 }
860 if (!rel.getParentName().isPersited()) {
861 nameService.save(rel.getParentName());
862 }
863 }
864 }
865 if (taxon == null){
866 taxon = newTaxonNode.getTaxon();
867 }
868 taxon.removeTaxonNode(newTaxonNode);
869
870 if (taxon.getSec() != null && taxon.getSec().isPersited()){
871 Reference sec = referenceService.load(taxon.getSec().getUuid());
872 taxon.setSec(sec);
873 }
874 if (taxon.getId() == 0){
875 UUID taxonUUID = taxonService.saveOrUpdate(taxon);
876 taxon = (Taxon) taxonService.load(taxonUUID);
877
878 }
879
880
881 TaxonNode parent = dao.load(parentUuid);
882 TaxonNode child = null;
883 try{
884 child = parent.addChildTaxon(taxon, newTaxonNode.getReference(), newTaxonNode.getMicroReference());
885
886 }catch(Exception e){
887 result.addException(e);
888 result.setError();
889 return result;
890 }
891
892 child.setUnplaced(newTaxonNode.isUnplaced());
893 child.setExcluded(newTaxonNode.isExcluded());
894 child.setDoubtful(newTaxonNode.isDoubtful());
895 for (TaxonNodeAgentRelation agentRel :newTaxonNode.getAgentRelations()){
896 child.addAgentRelation(agentRel.getType(), agentRel.getAgent());
897 }
898 for (Entry<Language, LanguageString> entry: newTaxonNode.getExcludedNote().entrySet()){
899 child.putExcludedNote(entry.getKey(), entry.getValue().getText());
900 }
901
902 newTaxonNode = null;
903 dao.saveOrUpdate(child);
904
905 result.addUpdatedObject(child.getParent());
906 if (child != null){
907 result.setCdmEntity(child);
908 }
909 return result;
910
911
912 }
913
914
915
916 @Override
917 @Transactional
918 public UpdateResult createNewTaxonNode(UUID parentNodeUuid, UUID taxonUuid, Reference ref, String microref){
919 UpdateResult result = new UpdateResult();
920 TaxonNode parent = dao.load(parentNodeUuid);
921 Taxon taxon = (Taxon) taxonService.load(taxonUuid);
922 TaxonNode child = null;
923 try{
924 child = parent.addChildTaxon(taxon, parent.getReference(), parent.getMicroReference());
925 }catch(Exception e){
926 result.addException(e);
927 result.setError();
928 return result;
929 }
930 // child = dao.save(child);
931
932 // dao.saveOrUpdate(child);
933 result.addUpdatedObject(parent);
934 if (child != null){
935 result.setCdmEntity(child);
936 }
937 return result;
938
939 }
940
941 @Override
942 @Transactional
943 public UpdateResult addTaxonNodeAgentRelation(UUID taxonNodeUUID, UUID agentUUID, DefinedTerm relationshipType){
944 UpdateResult result = new UpdateResult();
945 TaxonNode node = dao.load(taxonNodeUUID);
946 TeamOrPersonBase<?> agent = (TeamOrPersonBase<?>) agentService.load(agentUUID);
947 node.addAgentRelation(relationshipType, agent);
948 try{
949 dao.merge(node, true);
950 }catch (Exception e){
951 result.setError();
952 result.addException(e);
953 }
954 result.setCdmEntity(node);
955 return result;
956 }
957
958 @Override
959 @Transactional(readOnly=false)
960 public UpdateResult setSecundumForSubtree(SecundumForSubtreeConfigurator config) {
961 UpdateResult result = new UpdateResult();
962 IProgressMonitor monitor = config.getMonitor();
963
964 if (monitor == null){
965 monitor = DefaultProgressMonitor.NewInstance();
966 }
967 TaxonNode subTree = load(config.getSubtreeUuid());
968 TreeIndex subTreeIndex = null;
969 Reference newSec = null;
970 if (config.getNewSecundum() != null){
971 newSec = refService.load(config.getNewSecundum().getUuid());
972 }
973
974 if (config.getSubtreeUuid() == null){
975 result.setError();
976 result.addException(new NullPointerException("No subtree given"));
977 monitor.done();
978 return result;
979 }
980
981 if (subTree == null){
982 result.setError();
983 result.addException(new NullPointerException("Subtree does not exist"));
984 monitor.done();
985 return result;
986 }else{
987 subTreeIndex = TreeIndex.NewInstance(subTree.treeIndex());
988 int count = config.isIncludeAcceptedTaxa() ? dao.countSecundumForSubtreeAcceptedTaxa(subTreeIndex, newSec, config.isOverwriteExistingAccepted(), config.isIncludeSharedTaxa(), config.isEmptySecundumDetail()):0;
989 count += config.isIncludeSynonyms() ? dao.countSecundumForSubtreeSynonyms(subTreeIndex, newSec, config.isOverwriteExistingSynonyms(), config.isIncludeSharedTaxa() , config.isEmptySecundumDetail()) :0;
990 monitor.beginTask("Update Secundum Reference", count);
991 }
992
993 //Reference ref = config.getNewSecundum();
994 if (config.isIncludeAcceptedTaxa()){
995 monitor.subTask("Update Accepted Taxa");
996
997 Set<TaxonBase> updatedTaxa = dao.setSecundumForSubtreeAcceptedTaxa(subTreeIndex, newSec, config.isOverwriteExistingAccepted(), config.isIncludeSharedTaxa(), config.isEmptySecundumDetail(), monitor);
998 result.addUpdatedObjects(updatedTaxa);
999 }
1000 if (config.isIncludeSynonyms()){
1001 monitor.subTask("Update Synonyms");
1002 Set<TaxonBase> updatedSynonyms = dao.setSecundumForSubtreeSynonyms(subTreeIndex, newSec, config.isOverwriteExistingSynonyms(), config.isIncludeSharedTaxa() , config.isEmptySecundumDetail(), monitor);
1003 result.addUpdatedObjects(updatedSynonyms);
1004 }
1005
1006 monitor.done();
1007 return result;
1008 }
1009
1010
1011 @Override
1012 @Transactional(readOnly=false)
1013 public UpdateResult setPublishForSubtree(PublishForSubtreeConfigurator config){
1014 UpdateResult result = new UpdateResult();
1015 IProgressMonitor monitor = config.getMonitor();
1016 if (monitor == null){
1017 monitor = DefaultProgressMonitor.NewInstance();
1018 }
1019 TreeIndex subTreeIndex = null;
1020
1021 if (config.getSubtreeUuid() == null){
1022 result.setError();
1023 result.addException(new NullPointerException("No subtree given"));
1024 monitor.done();
1025 return result;
1026 }
1027 TaxonNode subTree = find(config.getSubtreeUuid());
1028 boolean includeAcceptedTaxa = config.isIncludeAcceptedTaxa();
1029 boolean publish = config.isPublish();
1030 boolean includeSynonyms = config.isIncludeSynonyms();
1031 boolean includeSharedTaxa = config.isIncludeSharedTaxa();
1032 boolean includeHybrids = config.isIncludeHybrids();
1033 boolean includeRelatedTaxa = config.isIncludeProParteSynonyms() || config.isIncludeMisapplications();
1034 if (subTree == null){
1035 result.setError();
1036 result.addException(new NullPointerException("Subtree does not exist"));
1037 monitor.done();
1038 return result;
1039 }else{
1040 subTreeIndex = TreeIndex.NewInstance(subTree.treeIndex());
1041 int count = includeAcceptedTaxa ? dao.countPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
1042 count += includeSynonyms ? dao.countPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
1043 count += includeRelatedTaxa ? dao.countPublishForSubtreeRelatedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids):0;
1044 monitor.beginTask("Update publish flag", count);
1045 }
1046
1047
1048 if (includeAcceptedTaxa){
1049 monitor.subTask("Update Accepted Taxa");
1050 Set<TaxonBase> updatedTaxa = dao.setPublishForSubtreeAcceptedTaxa(subTreeIndex, publish, includeSharedTaxa, includeHybrids, monitor);
1051 result.addUpdatedObjects(updatedTaxa);
1052 }
1053 if (includeSynonyms){
1054 monitor.subTask("Update Synonyms");
1055 Set<TaxonBase> updatedSynonyms = dao.setPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa, includeHybrids, monitor);
1056 result.addUpdatedObjects(updatedSynonyms);
1057 }
1058 if (includeRelatedTaxa){
1059 monitor.subTask("Update Related Taxa");
1060 Set<UUID> relationTypes = new HashSet<>();
1061 if (config.isIncludeMisapplications()){
1062 relationTypes.addAll(TaxonRelationshipType.misappliedNameUuids());
1063 }
1064 if (config.isIncludeProParteSynonyms()){
1065 relationTypes.addAll(TaxonRelationshipType.proParteOrPartialSynonymUuids());
1066 }
1067 Set<TaxonBase> updatedTaxa = dao.setPublishForSubtreeRelatedTaxa(subTreeIndex, publish,
1068 relationTypes, includeSharedTaxa, includeHybrids, monitor);
1069 result.addUpdatedObjects(updatedTaxa);
1070 }
1071
1072 monitor.done();
1073 return result;
1074 }
1075
1076 @Override
1077 public long count(TaxonNodeFilter filter){
1078 return nodeFilterDao.count(filter);
1079 }
1080
1081 @Override
1082 public List<UUID> uuidList(TaxonNodeFilter filter){
1083 return nodeFilterDao.listUuids(filter);
1084 }
1085
1086 @Override
1087 public List<Integer> idList(TaxonNodeFilter filter){
1088 return nodeFilterDao.idList(filter);
1089 }
1090
1091 @Override
1092 public TaxonNodeDto findCommonParentDto(Collection<TaxonNodeDto> nodes) {
1093 TaxonNodeDto commonParent = null;
1094 List<String> treePath = null;
1095 for (TaxonNodeDto nodeDto : nodes) {
1096 String nodeTreeIndex = nodeDto.getTreeIndex();
1097 nodeTreeIndex = nodeTreeIndex.replaceFirst("#", "");
1098 String[] split = nodeTreeIndex.split("#");
1099 if(treePath == null){
1100 treePath = Arrays.asList(split);
1101 }
1102 else{
1103 List<String> match = new ArrayList<>();
1104 for(int i=0;i<treePath.size();i++){
1105 if(i>=split.length){
1106 //current tree index is shorter so break
1107 break;
1108 }
1109 else if(split[i].equals(treePath.get(i))){
1110 //match found
1111 match.add(treePath.get(i));
1112 }
1113 else{
1114 //first mismatch found
1115 break;
1116 }
1117 }
1118 treePath = match;
1119 if(treePath.isEmpty()){
1120 //no common parent found for at least two nodes
1121 //-> they belong to a different classification
1122 break;
1123 }
1124 }
1125 }
1126 if(treePath!=null && !treePath.isEmpty()) {
1127 //get last index
1128 int nodeId = Integer.parseInt(treePath.get(treePath.size()-1));
1129 TaxonNode taxonNode = dao.load(nodeId, null);
1130 commonParent = new TaxonNodeDto(taxonNode);
1131 }
1132 return commonParent;
1133 }
1134
1135 @Override
1136 public List<TaxonDistributionDTO> getTaxonDistributionDTOForSubtree(UUID parentNodeUuid, List<String> propertyPaths, Authentication authentication){
1137 List<TaxonNode> nodes = listChildrenOf(load(parentNodeUuid), null, null,
1138 true, true, propertyPaths);
1139 List<TaxonDistributionDTO> result = new ArrayList<>();
1140 boolean hasPermission = false;
1141 //TaxonDescription instance = TaxonDescription.NewInstance();
1142 //hasPermission = permissionEvaluator.hasPermission(authentication, instance, Operation.UPDATE);
1143 for(TaxonNode node:nodes){
1144 if (authentication != null ) {
1145 hasPermission = permissionEvaluator.hasPermission(authentication, node, Operation.UPDATE);
1146 }else {
1147 hasPermission = true;
1148 }
1149 if (node.getTaxon() != null && hasPermission){
1150 try{
1151 TaxonDistributionDTO dto = new TaxonDistributionDTO(node.getTaxon());
1152 result.add(dto);
1153 }catch(Exception e){
1154 logger.error(e.getMessage(), e);
1155 }
1156
1157 }
1158
1159 }
1160
1161 return result;
1162 }
1163
1164 @Override
1165 public <S extends TaxonNode> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
1166 Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths) {
1167 return page(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, INCLUDE_UNPUBLISHED);
1168 }
1169
1170 @Override
1171 public <S extends TaxonNode> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
1172 Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths, boolean includeUnpublished) {
1173
1174 List<S> records;
1175 long resultSize = dao.count(clazz, restrictions);
1176 if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
1177 records = dao.list(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, includeUnpublished);
1178 } else {
1179 records = new ArrayList<>();
1180 }
1181 Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
1182 return pager;
1183 }
1184
1185 @Override
1186 public List<TaxonDistributionDTO> getTaxonDistributionDTOForSubtree(UUID parentNodeUuid,
1187 List<String> propertyPaths) {
1188 return getTaxonDistributionDTOForSubtree(parentNodeUuid, propertyPaths, null);
1189 }
1190
1191 @Override
1192 public List<TaxonNodeDto> getTaxonNodeDto(Integer limit, String pattern, UUID classificationUuid) {
1193 return dao.getTaxonNodeDto(limit, pattern, classificationUuid);
1194 }
1195
1196 @Override
1197 public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(ITaxonTreeNode parent) {
1198 UUID uuid = parent.getUuid();
1199 int id = parent.getId();
1200 UuidAndTitleCache<TaxonNode> uuidAndTitleCache = new UuidAndTitleCache<>(uuid, id, null);
1201 return listChildNodesAsUuidAndTitleCache(uuidAndTitleCache);
1202 }
1203
1204 @Override
1205 public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache<TaxonNode> parent) {
1206 return dao.listChildNodesAsUuidAndTitleCache(parent);
1207 }
1208 }