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