2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.api
.service
;
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
.HashMap
;
18 import java
.util
.HashSet
;
19 import java
.util
.List
;
22 import java
.util
.TreeMap
;
23 import java
.util
.UUID
;
24 import java
.util
.stream
.Collectors
;
26 import javax
.persistence
.EntityNotFoundException
;
28 import org
.apache
.commons
.collections
.CollectionUtils
;
29 import org
.apache
.commons
.lang
.StringUtils
;
30 import org
.apache
.log4j
.Logger
;
31 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
32 import org
.springframework
.stereotype
.Service
;
33 import org
.springframework
.transaction
.annotation
.Transactional
;
35 import eu
.etaxonomy
.cdm
.api
.service
.config
.CreateHierarchyForClassificationConfigurator
;
36 import eu
.etaxonomy
.cdm
.api
.service
.config
.NodeDeletionConfigurator
.ChildHandling
;
37 import eu
.etaxonomy
.cdm
.api
.service
.config
.SubtreeCloneConfigurator
;
38 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonDeletionConfigurator
;
39 import eu
.etaxonomy
.cdm
.api
.service
.dto
.EntityDTO
;
40 import eu
.etaxonomy
.cdm
.api
.service
.dto
.GroupedTaxonDTO
;
41 import eu
.etaxonomy
.cdm
.api
.service
.dto
.MarkedEntityDTO
;
42 import eu
.etaxonomy
.cdm
.api
.service
.dto
.TaxonInContextDTO
;
43 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
44 import eu
.etaxonomy
.cdm
.api
.service
.pager
.PagerUtils
;
45 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.AbstractPagerImpl
;
46 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
47 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
48 import eu
.etaxonomy
.cdm
.exception
.FilterException
;
49 import eu
.etaxonomy
.cdm
.exception
.UnpublishedException
;
50 import eu
.etaxonomy
.cdm
.hibernate
.HHH_9751_Util
;
51 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
52 import eu
.etaxonomy
.cdm
.model
.common
.ITreeNode
;
53 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
54 import eu
.etaxonomy
.cdm
.model
.common
.TreeIndex
;
55 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
56 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
57 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
58 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
59 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
60 import eu
.etaxonomy
.cdm
.model
.name
.INonViralName
;
61 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
62 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
63 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
64 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
65 import eu
.etaxonomy
.cdm
.model
.taxon
.ITaxonNodeComparator
;
66 import eu
.etaxonomy
.cdm
.model
.taxon
.ITaxonTreeNode
;
67 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
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
.TaxonRelationship
;
72 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
73 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.IBeanInitializer
;
74 import eu
.etaxonomy
.cdm
.persistence
.dao
.reference
.IReferenceDao
;
75 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.IClassificationDao
;
76 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
77 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeDao
;
78 import eu
.etaxonomy
.cdm
.persistence
.dao
.term
.IDefinedTermDao
;
79 import eu
.etaxonomy
.cdm
.persistence
.dto
.ClassificationLookupDTO
;
80 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
81 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonStatus
;
82 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
83 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
84 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
85 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImpl
;
92 @Transactional(readOnly
= true)
93 public class ClassificationServiceImpl
94 extends IdentifiableServiceBase
<Classification
, IClassificationDao
>
95 implements IClassificationService
{
97 private static final Logger logger
= Logger
.getLogger(ClassificationServiceImpl
.class);
100 private ITaxonNodeDao taxonNodeDao
;
103 private ITaxonDao taxonDao
;
106 private ITaxonNodeService taxonNodeService
;
109 private IReferenceDao referenceDao
;
112 private IDefinedTermDao termDao
;
115 private IBeanInitializer defaultBeanInitializer
;
119 protected void setDao(IClassificationDao dao
) {
123 private Comparator
<?
super TaxonNode
> taxonNodeComparator
;
126 public void setTaxonNodeComparator(ITaxonNodeComparator
<?
super TaxonNode
> taxonNodeComparator
){
127 this.taxonNodeComparator
= (Comparator
<?
super TaxonNode
>) taxonNodeComparator
;
131 public TaxonNode
loadTaxonNodeByTaxon(Taxon taxon
, UUID classificationUuid
, List
<String
> propertyPaths
){
132 Classification tree
= dao
.load(classificationUuid
);
133 TaxonNode node
= tree
.getNode(taxon
);
135 return loadTaxonNode(node
.getUuid(), propertyPaths
);
138 public TaxonNode
loadTaxonNode(UUID taxonNodeUuid
, List
<String
> propertyPaths
){
139 return taxonNodeDao
.load(taxonNodeUuid
, propertyPaths
);
143 @Transactional(readOnly
= false)
144 public UpdateResult
cloneClassification(SubtreeCloneConfigurator config
) {
145 UpdateResult result
= new UpdateResult();
147 if (config
.getSubTreeUuids().isEmpty()){
151 //TODO error handling
152 Reference taxonSecundum
= config
.isReuseTaxa() || config
.isReuseTaxonSecundum() || config
.getTaxonSecundumUuid() == null ?
153 null : referenceDao
.findByUuid(config
.getTaxonSecundumUuid());
154 config
.setTaxonSecundum(taxonSecundum
);
156 Reference parentChildReference
= config
.isReuseParentChildReference() || config
.getParentChildReferenceUuid() == null ?
157 null : referenceDao
.findByUuid(config
.getParentChildReferenceUuid());
158 config
.setParentChildReference(parentChildReference
);
160 Reference taxonRelationshipReference
= config
.getRelationTypeToOldTaxon() == null ?
161 null : referenceDao
.findByUuid(config
.getRelationshipReferenceUuid());
162 config
.setRelationshipReference(taxonRelationshipReference
);
164 Classification classificationClone
= Classification
.NewInstance(config
.getClassificationName());
166 if (config
.isReuseClassificationReference()){
167 TaxonNode anyNode
= taxonNodeDao
.findByUuid(config
.getSubTreeUuids().iterator().next());
168 if (anyNode
!= null){
169 Reference oldClassificationRef
= anyNode
.getClassification().getReference();
170 classificationClone
.setReference(oldClassificationRef
);
172 }else if (config
.getClassificationReferenceUuid() != null) {
173 Reference classificationReference
= referenceDao
.findByUuid(config
.getClassificationReferenceUuid());
174 classificationClone
.setReference(classificationReference
);
177 //clone taxa and taxon nodes
178 // List<Integer> childNodeIds = taxonNodeService.idList(taxonNodeFilter);
179 // List<TaxonNode> childNodes = taxonNodeService.loadByIds(childNodeIds, null);
180 List
<TaxonNode
> rootNodes
= taxonNodeService
.find(config
.getSubTreeUuids());
181 for (TaxonNode taxonNode
: rootNodes
) {
182 addChildTaxaToClone(taxonNode
, classificationClone
.getRootNode(), config
);
184 dao
.saveOrUpdate(classificationClone
);
185 result
.setCdmEntity(classificationClone
);
189 private void addChildTaxaToClone(TaxonNode originalParentNode
, TaxonNode parentNodeClone
,
190 SubtreeCloneConfigurator config
){
192 Taxon originalTaxon
= CdmBase
.deproxy(originalParentNode
.getTaxon());
193 if (originalTaxon
== null){
194 for (TaxonNode originalChildChildNode
: originalParentNode
.getChildNodes()) {
195 addChildTaxaToClone(originalChildChildNode
, parentNodeClone
, config
);
198 TaxonNode childNodeClone
;
199 String microReference
= null;
200 if (config
.isReuseTaxa()){
201 childNodeClone
= parentNodeClone
.addChildTaxon(originalTaxon
, config
.getParentChildReference(), microReference
);
203 Taxon cloneTaxon
= originalTaxon
.clone(config
.isIncludeSynonymsIncludingManAndProParte(),
204 config
.isIncludeTaxonRelationshipsExcludingManAndProParte(),
205 config
.isIncludeDescriptiveData(), config
.isIncludeMedia());
208 if (!config
.isReuseNames()){
209 cloneTaxon
.setName(cloneTaxon
.getName().clone());
212 if (!config
.isReuseTaxonSecundum()){
213 cloneTaxon
.setSec(config
.getTaxonSecundum());
216 //add relation between taxa
217 if (config
.getRelationTypeToOldTaxon() != null){
218 TaxonRelationship rel
= cloneTaxon
.addTaxonRelation(originalParentNode
.getTaxon(), config
.getRelationTypeToOldTaxon(),
219 config
.getRelationshipReference(), microReference
);
220 rel
.setDoubtful(config
.isRelationDoubtful());
222 childNodeClone
= parentNodeClone
.addChildTaxon(cloneTaxon
, config
.getParentChildReference(), microReference
);
225 //probably necessary as taxon nodes do not cascade
226 taxonNodeDao
.saveOrUpdate(childNodeClone
);
228 List
<TaxonNode
> originalChildNodes
= originalParentNode
.getChildNodes();
229 HHH_9751_Util
.removeAllNull(originalChildNodes
);
231 for (TaxonNode originalChildNode
: originalChildNodes
) {
232 addChildTaxaToClone(originalChildNode
, childNodeClone
, config
);
238 public List
<TaxonNode
> listRankSpecificRootNodes(Classification classification
,
239 TaxonNode subtree
, Rank rank
,
240 boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) {
241 return pageRankSpecificRootNodes(classification
, subtree
, rank
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
).getRecords();
245 public List
<TaxonNodeDto
> listRankSpecificRootNodeDtos(Classification classification
, TaxonNode subtree
,
246 Rank rank
, boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, TaxonNodeDtoSortMode sortMode
,
247 List
<String
> propertyPaths
) {
248 List
<TaxonNode
> list
= listRankSpecificRootNodes(classification
, subtree
, rank
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
249 return list
.stream().filter(e
-> e
!= null).map(e
-> new TaxonNodeDto(e
)).sorted(sortMode
.newComparator()).collect(Collectors
.toList());
253 public Pager
<TaxonNode
> pageRankSpecificRootNodes(Classification classification
, Rank rank
,
254 boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) {
255 return pageRankSpecificRootNodes(classification
, null, rank
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
259 public Pager
<TaxonNode
> pageRankSpecificRootNodes(Classification classification
, TaxonNode subtree
, Rank rank
,
260 boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) {
261 long[] numberOfResults
= dao
.countRankSpecificRootNodes(classification
, subtree
, includeUnpublished
, rank
);
262 long totalNumberOfResults
= numberOfResults
[0] + (numberOfResults
.length
> 1 ? numberOfResults
[1] : 0);
264 List
<TaxonNode
> results
= new ArrayList
<>();
266 if (AbstractPagerImpl
.hasResultsInRange(totalNumberOfResults
, pageIndex
, pageSize
)) { // no point checking again
267 Integer limit
= PagerUtils
.limitFor(pageSize
);
268 Integer start
= PagerUtils
.startFor(pageSize
, pageIndex
);
270 Integer remainingLimit
= limit
;
271 int[] queryIndexes
= rank
== null ?
new int[]{0} : new int[]{0,1};
273 for(int queryIndex
: queryIndexes
) {
274 if(start
!= null && start
> numberOfResults
[queryIndex
]) {
275 // start in next query with new start value
276 start
= start
- (int)numberOfResults
[queryIndex
];
280 List
<TaxonNode
> perQueryResults
= dao
.listRankSpecificRootNodes(classification
,
281 subtree
, rank
, includeUnpublished
, remainingLimit
,
282 start
, propertyPaths
, queryIndex
);
283 results
.addAll(perQueryResults
);
284 if(remainingLimit
!= null ){
285 remainingLimit
= remainingLimit
- results
.size();
286 if(remainingLimit
<= 0) {
287 // no need to run further queries if first query returned enough items!
290 // start at with fist item of next query to fetch the remaining items
295 // long start_t = System.currentTimeMillis();
296 Collections
.sort(results
, taxonNodeComparator
); // TODO is ordering during the hibernate query in the dao possible?
297 // System.err.println("service.pageRankSpecificRootNodes() - Collections.sort(results, taxonNodeComparator) " + (System.currentTimeMillis() - start_t));
298 return new DefaultPagerImpl
<>(pageIndex
, totalNumberOfResults
, pageSize
, results
);
303 public List
<TaxonNode
> loadTreeBranch(TaxonNode taxonNode
, Rank baseRank
,
304 boolean includeUnpublished
, List
<String
> propertyPaths
) throws UnpublishedException
{
305 return loadTreeBranch(taxonNode
, null, baseRank
, includeUnpublished
, propertyPaths
);
309 public List
<TaxonNode
> loadTreeBranch(TaxonNode taxonNode
, TaxonNode subtree
, Rank baseRank
,
310 boolean includeUnpublished
, List
<String
> propertyPaths
) throws UnpublishedException
{
312 TaxonNode thisNode
= taxonNodeDao
.load(taxonNode
.getUuid(), propertyPaths
);
313 if(baseRank
!= null){
314 baseRank
= (Rank
) termDao
.load(baseRank
.getUuid());
316 if (!includeUnpublished
&& thisNode
.getTaxon() != null && !thisNode
.getTaxon().isPublish()){
317 throw new UnpublishedException("Final taxon in tree branch is unpublished.");
320 List
<TaxonNode
> pathToRoot
= new ArrayList
<>();
321 pathToRoot
.add(thisNode
);
323 while(!thisNode
.isTopmostNode()){
324 //TODO why do we need to deproxy here?
325 // without this thisNode.getParent() will return NULL in
326 // some cases (environment dependend?) even if the parent exits
327 TaxonNode parentNode
= CdmBase
.deproxy(thisNode
).getParent();
329 if(parentNode
== null){
330 throw new NullPointerException("Taxon node " + thisNode
+ " must have a parent since it is not top most");
332 if(parentNode
.getTaxon() == null){
333 throw new NullPointerException("The taxon associated with taxon node " + parentNode
+ " is NULL");
335 if(!includeUnpublished
&& !parentNode
.getTaxon().isPublish()){
336 throw new UnpublishedException("Some taxon in tree branch is unpublished.");
338 if(parentNode
.getTaxon().getName() == null){
339 throw new NullPointerException("The name of the taxon associated with taxonNode " + parentNode
+ " is NULL");
342 Rank parentNodeRank
= (parentNode
.getTaxon().getName() == null) ?
null : parentNode
.getTaxon().getName().getRank();
343 // stop if the next parent is higher than the baseRank
344 if(baseRank
!= null && parentNodeRank
!= null && baseRank
.isLower(parentNodeRank
)){
347 if((subtree
!= null && !subtree
.isAncestor(parentNode
) )){
351 pathToRoot
.add(parentNode
);
352 thisNode
= parentNode
;
355 // initialize and invert order of nodes in list
356 defaultBeanInitializer
.initializeAll(pathToRoot
, propertyPaths
);
357 Collections
.reverse(pathToRoot
);
363 public List
<TaxonNode
> loadTreeBranchToTaxon(Taxon taxon
, Classification classification
, Rank baseRank
,
364 boolean includeUnpublished
, List
<String
> propertyPaths
) throws UnpublishedException
{
365 return loadTreeBranchToTaxon(taxon
, classification
, null, baseRank
, includeUnpublished
, propertyPaths
);
369 public List
<TaxonNodeDto
> loadTreeBranchDTOsToTaxon(Taxon taxon
, Classification classification
,
370 TaxonNode subtree
, Rank baseRank
,
371 boolean includeUnpublished
, List
<String
> propertyPaths
) throws UnpublishedException
{
372 List
<TaxonNode
> list
= loadTreeBranchToTaxon(taxon
, classification
, subtree
, baseRank
, includeUnpublished
, propertyPaths
);
373 return list
.stream().map(e
-> new TaxonNodeDto(e
)).collect(Collectors
.toList());
377 public List
<TaxonNode
> loadTreeBranchToTaxon(Taxon taxon
, Classification classification
,
378 TaxonNode subtree
, Rank baseRank
,
379 boolean includeUnpublished
, List
<String
> propertyPaths
) throws UnpublishedException
{
381 UUID nodeUuid
= getTaxonNodeUuidByTaxonUuid(classification
.getUuid(), taxon
.getUuid());
382 TaxonNode node
= taxonNodeService
.find(nodeUuid
);
384 logger
.warn("The specified taxon is not found in the given tree.");
386 }else if (subtree
!= null && !node
.isDescendant(subtree
)){
387 //TODO handle as exception? E.g. FilterException, AccessDeniedException?
388 logger
.warn("The specified taxon is not found for the given subtree.");
392 return loadTreeBranch(node
, subtree
, baseRank
, includeUnpublished
, propertyPaths
);
397 public List
<TaxonNode
> loadChildNodesOfTaxonNode(TaxonNode taxonNode
,
398 List
<String
> propertyPaths
) {
399 taxonNode
= taxonNodeDao
.load(taxonNode
.getUuid());
400 List
<TaxonNode
> childNodes
= new ArrayList
<TaxonNode
>(taxonNode
.getChildNodes());
401 defaultBeanInitializer
.initializeAll(childNodes
, propertyPaths
);
402 Collections
.sort(childNodes
, taxonNodeComparator
);
407 public List
<TaxonNode
> listChildNodesOfTaxon(UUID taxonUuid
, UUID classificationUuid
,
408 boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
){
410 return listChildNodesOfTaxon(taxonUuid
, classificationUuid
, null, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
411 } catch (FilterException e
) {
412 throw new RuntimeException(e
); //this should not happen as filter is null
417 public List
<TaxonNode
> listChildNodesOfTaxon(UUID taxonUuid
, UUID classificationUuid
, UUID subtreeUuid
,
418 boolean includeUnpublished
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) throws FilterException
{
420 Classification classification
= dao
.load(classificationUuid
);
421 Taxon taxon
= (Taxon
) taxonDao
.load(taxonUuid
);
422 TaxonNode subtree
= taxonNodeDao
.load(subtreeUuid
);
423 if (subtreeUuid
!= null && subtree
== null){
424 throw new FilterException("Taxon node for subtree filter can not be found in database", true);
427 List
<TaxonNode
> results
= dao
.listChildrenOf(
428 taxon
, classification
, subtree
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
429 Collections
.sort(results
, taxonNodeComparator
); // FIXME this is only a HACK, order during the hibernate query in the dao
434 public List
<TaxonNodeDto
> listChildNodeDtosOfTaxon(UUID taxonUuid
, UUID classificationUuid
, UUID subtreeUuid
, boolean includeUnpublished
,
435 Integer pageSize
, Integer pageIndex
, TaxonNodeDtoSortMode sortMode
, List
<String
> propertyPaths
) throws FilterException
{
436 Classification classification
= dao
.load(classificationUuid
);
437 Taxon taxon
= (Taxon
) taxonDao
.load(taxonUuid
);
438 TaxonNode subtree
= taxonNodeDao
.load(subtreeUuid
);
439 if (subtreeUuid
!= null && subtree
== null){
440 throw new FilterException("Taxon node for subtree filter can not be found in database", true);
443 List
<TaxonNode
> results
= dao
.listChildrenOf(
444 taxon
, classification
, subtree
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
445 Comparator
<TaxonNodeDto
> comparator
= sortMode
.newComparator();
446 // TODO order during the hibernate query in the dao?
447 List
<TaxonNodeDto
> dtos
= results
.stream().map(e
-> new TaxonNodeDto(e
)).sorted(comparator
).collect(Collectors
.toList());
452 public Pager
<TaxonNode
> pageSiblingsOfTaxon(UUID taxonUuid
, UUID classificationUuid
, boolean includeUnpublished
,
453 Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
){
455 Classification classification
= dao
.load(classificationUuid
);
456 Taxon taxon
= (Taxon
) taxonDao
.load(taxonUuid
);
458 long numberOfResults
= dao
.countSiblingsOf(taxon
, classification
, includeUnpublished
);
460 List
<TaxonNode
> results
;
461 if(PagerUtils
.hasResultsInRange(numberOfResults
, pageIndex
, pageSize
)) {
462 results
= dao
.listSiblingsOf(taxon
, classification
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
463 Collections
.sort(results
, taxonNodeComparator
); // FIXME this is only a HACK, order during the hibernate query in the dao
465 results
= new ArrayList
<>();
468 return new DefaultPagerImpl
<>(pageIndex
, numberOfResults
, pageSize
, results
);
472 public List
<TaxonNode
> listSiblingsOfTaxon(UUID taxonUuid
, UUID classificationUuid
, boolean includeUnpublished
,
473 Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
){
475 Pager
<TaxonNode
> pager
= pageSiblingsOfTaxon(taxonUuid
, classificationUuid
, includeUnpublished
, pageSize
, pageIndex
, propertyPaths
);
476 return pager
.getRecords();
480 public ITaxonTreeNode
getTreeNodeByUuid(UUID uuid
){
481 ITaxonTreeNode treeNode
= taxonNodeDao
.findByUuid(uuid
);
482 if(treeNode
== null){
483 treeNode
= dao
.findByUuid(uuid
);
490 public TaxonNode
getRootNode(UUID classificationUuid
){
491 return dao
.getRootNode(classificationUuid
);
495 public List
<Classification
> listClassifications(Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
496 return dao
.list(limit
, start
, orderHints
, propertyPaths
);
500 public UUID
removeTaxonNode(TaxonNode taxonNode
) {
501 return taxonNodeDao
.delete(taxonNode
);
504 public UUID
removeTreeNode(ITaxonTreeNode treeNode
) {
505 if(treeNode
instanceof Classification
){
506 return dao
.delete((Classification
) treeNode
);
507 }else if(treeNode
instanceof TaxonNode
){
508 return taxonNodeDao
.delete((TaxonNode
)treeNode
);
513 public UUID
saveTaxonNode(TaxonNode taxonNode
) {
514 return taxonNodeDao
.save(taxonNode
).getUuid();
518 public Map
<UUID
, TaxonNode
> saveTaxonNodeAll(
519 Collection
<TaxonNode
> taxonNodeCollection
) {
520 return taxonNodeDao
.saveAll(taxonNodeCollection
);
524 public UUID
saveClassification(Classification classification
) {
526 taxonNodeDao
.saveOrUpdateAll(classification
.getAllNodes());
527 UUID result
=dao
.saveOrUpdate(classification
);
532 public UUID
saveTreeNode(ITaxonTreeNode treeNode
) {
533 if(treeNode
instanceof Classification
){
534 return dao
.save((Classification
) treeNode
).getUuid();
535 }else if(treeNode
instanceof TaxonNode
){
536 return taxonNodeDao
.save((TaxonNode
)treeNode
).getUuid();
542 public List
<TaxonNode
> getAllNodes(){
543 return taxonNodeDao
.list(null,null);
547 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(UUID classificationUuid
, Integer limit
, String pattern
, boolean searchForClassifications
, boolean includeDoubtful
) {
548 return taxonNodeDao
.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(dao
.load(classificationUuid
), limit
, pattern
, searchForClassifications
, includeDoubtful
);
552 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(Classification classification
, Integer limit
, String pattern
, boolean searchForClassifications
) {
553 return taxonNodeDao
.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classification
, limit
, pattern
, searchForClassifications
);
557 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(UUID classificationUuid
, boolean searchForClassifications
) {
558 return taxonNodeDao
.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(dao
.load(classificationUuid
), null, null, searchForClassifications
);
562 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(Classification classification
, boolean searchForClassifications
) {
563 return taxonNodeDao
.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classification
, null, null, searchForClassifications
);
567 public List
<UuidAndTitleCache
<Classification
>> getUuidAndTitleCache(Integer limit
, String pattern
) {
568 return dao
.getUuidAndTitleCache(limit
, pattern
);
572 public Map
<UUID
, List
<MediaRepresentation
>> getAllMediaForChildNodes(
573 TaxonNode taxonNode
, List
<String
> propertyPaths
, int size
,
574 int height
, int widthOrDuration
, String
[] mimeTypes
) {
576 TreeMap
<UUID
, List
<MediaRepresentation
>> result
= new TreeMap
<>();
577 List
<MediaRepresentation
> mediaRepresentations
= new ArrayList
<>();
579 //add all media of the children to the result map
580 if (taxonNode
!= null){
582 List
<TaxonNode
> nodes
= new ArrayList
<>();
584 nodes
.add(loadTaxonNode(taxonNode
.getUuid(), propertyPaths
));
585 nodes
.addAll(loadChildNodesOfTaxonNode(taxonNode
, propertyPaths
));
587 for(TaxonNode node
: nodes
){
588 Taxon taxon
= node
.getTaxon();
589 for (TaxonDescription taxonDescription
: taxon
.getDescriptions()){
590 for (DescriptionElementBase descriptionElement
: taxonDescription
.getElements()){
591 for(Media media
: descriptionElement
.getMedia()){
592 //find the best matching representation
593 mediaRepresentations
.add(MediaUtils
.findBestMatchingRepresentation(media
,null, size
, height
, widthOrDuration
, mimeTypes
, MediaUtils
.MissingValueStrategy
.MAX
));
597 result
.put(taxon
.getUuid(), mediaRepresentations
);
605 @Transactional(readOnly
= false)
606 public UpdateResult
updateCaches(Class
<?
extends Classification
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<Classification
> cacheStrategy
, IProgressMonitor monitor
) {
608 clazz
= Classification
.class;
610 return super.updateCachesImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
615 * @param allNodesOfClassification
616 * @return null - if allNodesOfClassification is empty <br>
619 private Map
<String
, List
<TaxonNode
>> getSortedGenusList(Collection
<TaxonNode
> allNodesOfClassification
){
621 if(allNodesOfClassification
== null || allNodesOfClassification
.isEmpty()){
624 Map
<String
, List
<TaxonNode
>> sortedGenusMap
= new HashMap
<>();
625 for(TaxonNode node
:allNodesOfClassification
){
626 Taxon taxon
= node
.getTaxon();
627 INonViralName name
= taxon
.getName();
628 String genusOrUninomial
= name
.getGenusOrUninomial();
629 //if rank unknown split string and take first word
630 if(genusOrUninomial
== null){
631 String titleCache
= taxon
.getTitleCache();
632 String
[] split
= titleCache
.split("\\s+");
634 genusOrUninomial
= s
;
638 //if node has children
640 //retrieve list from map if not create List
641 if(sortedGenusMap
.containsKey(genusOrUninomial
)){
642 List
<TaxonNode
> list
= sortedGenusMap
.get(genusOrUninomial
);
644 sortedGenusMap
.put(genusOrUninomial
, list
);
646 //create List for genus
647 List
<TaxonNode
> list
= new ArrayList
<>();
649 sortedGenusMap
.put(genusOrUninomial
, list
);
652 return sortedGenusMap
;
657 * creates new Classification and parent TaxonNodes at genus level
660 * @param map GenusMap which holds a name (Genus) and all the same Taxa as a list
661 * @param classification you want to improve the hierarchy (will not be modified)
662 * @param configurator to change certain settings, if null then standard settings will be taken
663 * @return new classification with parentNodes for each entry in the map
665 @SuppressWarnings({ "unchecked" })
666 @Transactional(readOnly
= false)
668 public UpdateResult
createHierarchyInClassification(Classification classification
, CreateHierarchyForClassificationConfigurator configurator
){
669 UpdateResult result
= new UpdateResult();
670 classification
= dao
.findByUuid(classification
.getUuid());
671 Map
<String
, List
<TaxonNode
>> map
= getSortedGenusList(classification
.getAllNodes());
673 final String APPENDIX
= "repaired";
674 String titleCache
= StringUtils
.isBlank(classification
.getTitleCache()) ?
" " : classification
.getTitleCache() ;
675 //TODO classification clone???
676 Classification newClassification
= Classification
.NewInstance(titleCache
+" "+ APPENDIX
);
677 newClassification
.setReference(classification
.getReference());
679 for(Map
.Entry
<String
, List
<TaxonNode
>> entry
:map
.entrySet()){
680 String genus
= entry
.getKey();
681 List
<TaxonNode
> listOfTaxonNodes
= entry
.getValue();
682 TaxonNode parentNode
= null;
683 //Search for genus in list
684 for(TaxonNode tNode
:listOfTaxonNodes
){
685 //take that taxonNode as parent and remove from list with all it possible children
687 TaxonName name
= tNode
.getTaxon().getName();
688 if(name
.getNameCache().equalsIgnoreCase(genus
)){
689 TaxonNode clone
= tNode
.clone();
690 if(!tNode
.hasChildNodes()){
691 //FIXME remove classification
692 // parentNode = newClassification.addChildNode(clone, 0, classification.getCitation(), classification.getMicroReference());
693 parentNode
= newClassification
.addChildNode(clone
, 0, clone
.getReference(), clone
.getMicroReference());
694 //remove taxonNode from list because just added to classification
695 result
.addUpdatedObject(tNode
);
696 listOfTaxonNodes
.remove(tNode
);
699 //save prior Hierarchy and remove them from the list
700 List
<TaxonNode
> copyAllChildrenToTaxonNode
= copyAllChildrenToTaxonNode(tNode
, clone
, result
);
701 // parentNode = newClassification.addChildNode(clone, 0, classification.getCitation(), classification.getMicroReference());
702 //FIXME remove classification
703 parentNode
= newClassification
.addChildNode(clone
, 0, clone
.getReference(), clone
.getMicroReference());
704 //remove taxonNode from list because just added to classification
705 result
.addUpdatedObject(tNode
);
706 listOfTaxonNodes
.remove(tNode
);
707 if(copyAllChildrenToTaxonNode
!= null){
708 listOfTaxonNodes
= (List
<TaxonNode
>) CollectionUtils
.removeAll(listOfTaxonNodes
, copyAllChildrenToTaxonNode
);
714 if(parentNode
== null){
715 //if no match found in list, create parentNode
716 NonViralNameParserImpl parser
= NonViralNameParserImpl
.NewInstance();
717 TaxonName TaxonName
= (TaxonName
)parser
.parseFullName(genus
);
718 //TODO Sec via configurator
719 Taxon taxon
= Taxon
.NewInstance(TaxonName
, null);
720 parentNode
= newClassification
.addChildTaxon(taxon
, 0, null, null);
721 result
.addUpdatedObject(parentNode
);
723 //iterate over the rest of the list
724 for(TaxonNode tn
: listOfTaxonNodes
){
725 //if TaxonNode has a parent and this is not the classification then skip it
726 //and add to new classification via the parentNode as children of it
727 //this should assures to keep the already existing hierarchy
728 //FIXME: Assert is not rootnode --> entrypoint is not classification in future but rather rootNode
730 if(!tn
.isTopmostNode()){
731 continue; //skip to next taxonNode
734 TaxonNode clone
= tn
.clone();
735 //FIXME: citation from node
736 //TODO: addchildNode without citation and references
737 // TaxonNode taxonNode = parentNode.addChildNode(clone, classification.getCitation(), classification.getMicroReference());
738 TaxonNode taxonNode
= parentNode
.addChildNode(clone
, clone
.getReference(), clone
.getMicroReference());
739 result
.addUnChangedObject(clone
);
740 if(tn
.hasChildNodes()){
741 //save hierarchy in new classification
742 List
<TaxonNode
> copyAllChildrenToTaxonNode
= copyAllChildrenToTaxonNode(tn
, taxonNode
, result
);
743 if(copyAllChildrenToTaxonNode
!= null){
744 listOfTaxonNodes
= (List
<TaxonNode
>) CollectionUtils
.removeAll(listOfTaxonNodes
, copyAllChildrenToTaxonNode
);
749 dao
.saveOrUpdate(newClassification
);
750 result
.setCdmEntity(newClassification
);
756 * recursive method to get all childnodes of taxonNode in classification.
758 * @param classification just for References and Citation, can be null
759 * @param copyFromNode TaxonNode with Children
760 * @param copyToNode TaxonNode which will receive the children
761 * @return List of ChildNode which has been added. If node has no children returns null
763 private List
<TaxonNode
> copyAllChildrenToTaxonNode(TaxonNode copyFromNode
, TaxonNode copyToNode
, UpdateResult result
) {
764 List
<TaxonNode
> childNodes
;
765 if(!copyFromNode
.hasChildNodes()){
768 childNodes
= copyFromNode
.getChildNodes();
770 for(TaxonNode childNode
:childNodes
){
771 TaxonNode clone
= childNode
.clone();
772 result
.addUnChangedObject(clone
);
773 if(childNode
.hasChildNodes()){
774 copyAllChildrenToTaxonNode(childNode
, clone
, result
);
776 //FIXME: citation from node instead of classification
777 // copyToNode.addChildNode(clone,classification.getCitation(), classification.getMicroReference());
778 copyToNode
.addChildNode(clone
, clone
.getReference(), clone
.getMicroReference());
784 public ClassificationLookupDTO
classificationLookup(Classification classification
) {
785 return dao
.classificationLookup(classification
);
790 public DeleteResult
delete(UUID classificationUuid
, TaxonDeletionConfigurator config
){
791 DeleteResult result
= new DeleteResult();
792 Classification classification
= dao
.findByUuid(classificationUuid
);
793 if (classification
== null){
794 result
.addException(new IllegalArgumentException("The classification does not exist in database."));
798 if (!classification
.hasChildNodes()){
799 dao
.delete(classification
);
800 result
.addDeletedObject(classification
);
803 if (config
.getTaxonNodeConfig().getChildHandling().equals(ChildHandling
.DELETE
)){
804 // TaxonNode root = classification.getRootNode();
805 // result.includeResult(taxonNodeService.deleteTaxonNode(HibernateProxyHelper.deproxy(root), config));
806 // result.addDeletedObject(classification);
807 dao
.delete(classification
);
808 result
.addDeletedObject(classification
);
817 public List
<GroupedTaxonDTO
> groupTaxaByHigherTaxon(List
<UUID
> originalTaxonUuids
, UUID classificationUuid
, Rank minRank
, Rank maxRank
){
818 List
<GroupedTaxonDTO
> result
= new ArrayList
<>();
820 //get treeindex for each taxonUUID
821 Map
<UUID
, TreeIndex
> taxonIdTreeIndexMap
= dao
.treeIndexForTaxonUuids(classificationUuid
, originalTaxonUuids
);
823 //build treeindex list (or tree)
824 //TODO make it work with TreeIndex or move there
825 List
<String
> treeIndexClosureStr
= new ArrayList
<>();
826 for (TreeIndex treeIndex
: taxonIdTreeIndexMap
.values()){
827 String
[] splits
= treeIndex
.toString().substring(1).split(ITreeNode
.separator
);
828 String currentIndex
= ITreeNode
.separator
;
829 for (String split
: splits
){
830 if (split
.equals("")){
833 currentIndex
+= split
+ ITreeNode
.separator
;
834 if (!treeIndexClosureStr
.contains(currentIndex
) && !split
.startsWith(ITreeNode
.treePrefix
)){
835 treeIndexClosureStr
.add(currentIndex
);
840 //get rank sortindex for all parent taxa with sortindex <= minRank and sortIndex >= maxRank (if available)
841 Integer minRankOrderIndex
= minRank
== null ?
null : minRank
.getOrderIndex();
842 Integer maxRankOrderIndex
= maxRank
== null ?
null : maxRank
.getOrderIndex();
843 List
<TreeIndex
> treeIndexClosure
= TreeIndex
.NewListInstance(treeIndexClosureStr
);
845 Map
<TreeIndex
, Integer
> treeIndexSortIndexMapTmp
= taxonNodeDao
.rankOrderIndexForTreeIndex(treeIndexClosure
, minRankOrderIndex
, maxRankOrderIndex
);
847 //remove all treeindex with "exists child in above map(and child.sortindex > xxx)
848 List
<TreeIndex
> treeIndexList
= TreeIndex
.sort(treeIndexSortIndexMapTmp
.keySet());
850 Map
<TreeIndex
, Integer
> treeIndexSortIndexMap
= new HashMap
<>();
851 TreeIndex lastTreeIndex
= null;
852 for (TreeIndex treeIndex
: treeIndexList
){
853 if (lastTreeIndex
!= null && lastTreeIndex
.hasChild(treeIndex
)){
854 treeIndexSortIndexMap
.remove(lastTreeIndex
);
856 treeIndexSortIndexMap
.put(treeIndex
, treeIndexSortIndexMapTmp
.get(treeIndex
));
857 lastTreeIndex
= treeIndex
;
860 //get taxonID for treeIndexes
861 Map
<TreeIndex
, UuidAndTitleCache
<?
>> treeIndexTaxonIdMap
= taxonNodeDao
.taxonUuidsForTreeIndexes(treeIndexSortIndexMap
.keySet());
864 for (UUID originalTaxonUuid
: originalTaxonUuids
){
865 GroupedTaxonDTO item
= new GroupedTaxonDTO();
867 item
.setTaxonUuid(originalTaxonUuid
);
868 TreeIndex groupTreeIndex
= taxonIdTreeIndexMap
.get(originalTaxonUuid
);
869 String groupIndexX
= TreeIndex
.toString(groupTreeIndex
);
870 while (groupTreeIndex
!= null){
871 if (treeIndexTaxonIdMap
.get(groupTreeIndex
) != null){
872 UuidAndTitleCache
<?
> uuidAndLabel
= treeIndexTaxonIdMap
.get(groupTreeIndex
);
873 item
.setGroupTaxonUuid(uuidAndLabel
.getUuid());
874 item
.setGroupTaxonName(uuidAndLabel
.getTitleCache());
877 groupTreeIndex
= groupTreeIndex
.parent();
878 // int index = groupIndex.substring(0, groupIndex.length()-1).lastIndexOf(ITreeNode.separator);
879 // groupIndex = index < 0 ? null : groupIndex.substring(0, index+1);
888 public List
<GroupedTaxonDTO
> groupTaxaByMarkedParents(List
<UUID
> originalTaxonUuids
, UUID classificationUuid
,
889 MarkerType markerType
, Boolean flag
) {
891 List
<GroupedTaxonDTO
> result
= new ArrayList
<>();
893 //get treeindex for each taxonUUID
894 Map
<UUID
, TreeIndex
> taxonIdTreeIndexMap
= dao
.treeIndexForTaxonUuids(classificationUuid
, originalTaxonUuids
);
896 //get all marked tree indexes
897 Set
<TreeIndex
> markedTreeIndexes
= dao
.getMarkedTreeIndexes(markerType
, flag
);
899 Map
<TreeIndex
, TreeIndex
> groupedMap
= TreeIndex
.group(markedTreeIndexes
, taxonIdTreeIndexMap
.values());
900 Set
<TreeIndex
> notNullGroups
= new HashSet
<>(groupedMap
.values());
901 notNullGroups
.remove(null);
903 //get taxonInfo for treeIndexes
904 Map
<TreeIndex
, UuidAndTitleCache
<?
>> treeIndexTaxonIdMap
= taxonNodeDao
.taxonUuidsForTreeIndexes(notNullGroups
);
907 for (UUID originalTaxonUuid
: originalTaxonUuids
){
908 GroupedTaxonDTO item
= new GroupedTaxonDTO();
910 item
.setTaxonUuid(originalTaxonUuid
);
912 TreeIndex toBeGroupedTreeIndex
= taxonIdTreeIndexMap
.get(originalTaxonUuid
);
913 TreeIndex groupTreeIndex
= groupedMap
.get(toBeGroupedTreeIndex
);
914 UuidAndTitleCache
<?
> uuidAndLabel
= treeIndexTaxonIdMap
.get(groupTreeIndex
);
915 if (uuidAndLabel
!= null){
916 item
.setGroupTaxonUuid(uuidAndLabel
.getUuid());
917 item
.setGroupTaxonName(uuidAndLabel
.getTitleCache());
925 public UUID
getTaxonNodeUuidByTaxonUuid(UUID classificationUuid
, UUID taxonUuid
) {
926 Map
<UUID
, UUID
> map
= dao
.getTaxonNodeUuidByTaxonUuid(classificationUuid
, Arrays
.asList(taxonUuid
));
927 UUID taxonNodeUuid
= map
.get(taxonUuid
);
928 return taxonNodeUuid
;
932 public TaxonInContextDTO
getTaxonInContext(UUID classificationUuid
, UUID taxonBaseUuid
,
933 Boolean doChildren
, Boolean doSynonyms
, boolean includeUnpublished
, List
<UUID
> ancestorMarkers
,
934 TaxonNodeSortMode sortMode
) {
936 TaxonInContextDTO result
= new TaxonInContextDTO();
938 TaxonBase
<?
> taxonBase
= taxonDao
.load(taxonBaseUuid
);
939 if (taxonBase
== null){
940 throw new EntityNotFoundException("Taxon with uuid " + taxonBaseUuid
+ " not found in datasource");
942 boolean isSynonym
= false;
944 if (taxonBase
.isInstanceOf(Synonym
.class)){
946 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
947 acceptedTaxon
= synonym
.getAcceptedTaxon();
948 if (acceptedTaxon
== null) {
949 throw new EntityNotFoundException("Accepted taxon not found for synonym" );
951 TaxonStatus taxonStatus
= TaxonStatus
.Synonym
;
952 if (synonym
.getName()!= null && acceptedTaxon
.getName() != null
953 && synonym
.getName().getHomotypicalGroup().equals(acceptedTaxon
.getName().getHomotypicalGroup())){
954 taxonStatus
= TaxonStatus
.SynonymObjective
;
956 result
.setTaxonStatus(taxonStatus
);
959 acceptedTaxon
= CdmBase
.deproxy(taxonBase
, Taxon
.class);
960 result
.setTaxonStatus(TaxonStatus
.Accepted
);
962 UUID acceptedTaxonUuid
= acceptedTaxon
.getUuid();
964 UUID taxonNodeUuid
= getTaxonNodeUuidByTaxonUuid(classificationUuid
, acceptedTaxonUuid
);
965 if (taxonNodeUuid
== null) {
966 throw new EntityNotFoundException("Taxon not found in classficiation with uuid " + classificationUuid
+ ". Either classification does not exist or does not contain taxon/synonym with uuid " + taxonBaseUuid
);
968 result
.setTaxonNodeUuid(taxonNodeUuid
);
970 //TODO make it a dao call
971 Taxon parentTaxon
= getParentTaxon(classificationUuid
, acceptedTaxon
);
972 if (parentTaxon
!= null){
973 result
.setParentTaxonUuid(parentTaxon
.getUuid());
974 result
.setParentTaxonLabel(parentTaxon
.getTitleCache());
975 if (parentTaxon
.getName() != null){
976 result
.setParentNameLabel(parentTaxon
.getName().getTitleCache());
980 result
.setTaxonUuid(taxonBaseUuid
);
981 result
.setClassificationUuid(classificationUuid
);
982 if (taxonBase
.getSec() != null){
983 result
.setSecundumUuid(taxonBase
.getSec().getUuid());
984 result
.setSecundumLabel(taxonBase
.getSec().getTitleCache());
986 result
.setTaxonLabel(taxonBase
.getTitleCache());
988 TaxonName name
= taxonBase
.getName();
989 result
.setNameUuid(name
.getUuid());
990 result
.setNameLabel(name
.getTitleCache());
991 result
.setNameWithoutAuthor(name
.getNameCache());
992 result
.setGenusOrUninomial(name
.getGenusOrUninomial());
993 result
.setInfraGenericEpithet(name
.getInfraGenericEpithet());
994 result
.setSpeciesEpithet(name
.getSpecificEpithet());
995 result
.setInfraSpecificEpithet(name
.getInfraSpecificEpithet());
997 result
.setAuthorship(name
.getAuthorshipCache());
999 Rank rank
= name
.getRank();
1001 result
.setRankUuid(rank
.getUuid());
1002 String rankLabel
= rank
.getAbbreviation();
1003 if (StringUtils
.isBlank(rankLabel
)){
1004 rankLabel
= rank
.getLabel();
1006 result
.setRankLabel(rankLabel
);
1009 boolean recursive
= false;
1010 Integer pageSize
= null;
1011 Integer pageIndex
= null;
1012 Pager
<TaxonNodeDto
> children
= taxonNodeService
.pageChildNodesDTOs(taxonNodeUuid
, recursive
, includeUnpublished
, doSynonyms
,
1013 sortMode
, pageSize
, pageIndex
);
1017 for (TaxonNodeDto childDto
: children
.getRecords()){
1018 if (doChildren
&& childDto
.getTaxonStatus().equals(TaxonStatus
.Accepted
)){
1019 EntityDTO
<Taxon
> child
= new EntityDTO
<Taxon
>(childDto
.getTaxonUuid(), childDto
.getTitleCache());
1020 result
.addChild(child
);
1021 }else if (doSynonyms
&& childDto
.getTaxonStatus().isSynonym()){
1022 EntityDTO
<Synonym
> child
= new EntityDTO
<>(childDto
.getTaxonUuid(), childDto
.getTitleCache());
1023 result
.addSynonym(child
);
1027 result
.setAcceptedTaxonUuid(acceptedTaxonUuid
);
1028 String nameTitel
= acceptedTaxon
.getName() == null ?
null : acceptedTaxon
.getName().getTitleCache();
1029 result
.setAcceptedTaxonLabel(acceptedTaxon
.getTitleCache());
1030 result
.setAcceptedNameLabel(nameTitel
);
1034 if (ancestorMarkers
!= null && !ancestorMarkers
.isEmpty()){
1035 @SuppressWarnings("rawtypes")
1036 List
<DefinedTermBase
> markerTypesTerms
= termDao
.list(ancestorMarkers
, pageSize
, null, null, null);
1037 List
<MarkerType
> markerTypes
= new ArrayList
<>();
1038 for (DefinedTermBase
<?
> term
: markerTypesTerms
){
1039 if (term
.isInstanceOf(MarkerType
.class)){
1040 markerTypes
.add(CdmBase
.deproxy(term
, MarkerType
.class));
1043 if (! markerTypes
.isEmpty()){
1044 TaxonNode node
= taxonNodeDao
.findByUuid(taxonNodeUuid
);
1045 handleAncestorsForMarkersRecursive(result
, markerTypes
, node
);
1052 private Taxon
getParentTaxon(UUID classificationUuid
, Taxon acceptedTaxon
) {
1053 if (classificationUuid
== null){
1056 TaxonNode parent
= null;
1057 for (TaxonNode node
: acceptedTaxon
.getTaxonNodes()){
1058 if (classificationUuid
.equals(node
.getClassification().getUuid())){
1059 parent
= node
.getParent();
1062 if (parent
!= null){
1063 return parent
.getTaxon();
1068 private void handleAncestorsForMarkersRecursive(TaxonInContextDTO result
, List
<MarkerType
> markerTypes
, TaxonNode node
) {
1069 for (MarkerType type
: markerTypes
){
1070 Taxon taxon
= node
.getTaxon();
1071 if (taxon
!= null && taxon
.hasMarker(type
, true)){
1072 String label
= taxon
.getName() == null? taxon
.getTitleCache() : taxon
.getName().getTitleCache();
1073 MarkedEntityDTO
<Taxon
> dto
= new MarkedEntityDTO
<>(type
, true, taxon
.getUuid(), label
);
1074 result
.addMarkedAncestor(dto
);
1077 TaxonNode parentNode
= node
.getParent();
1078 if (parentNode
!= null){
1079 handleAncestorsForMarkersRecursive(result
, markerTypes
, parentNode
);
1084 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1085 Classification classification
) {
1086 return getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classification
, false);
1090 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1091 UUID classificationUuid
) {
1092 return getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classificationUuid
, false);
1096 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1097 UUID classificationUuid
, Integer limit
, String pattern
) {
1098 return getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classificationUuid
, limit
, pattern
, false);
1102 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1103 Classification classification
, Integer limit
, String pattern
) {
1104 return getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classification
, limit
, pattern
, false);
1108 public List
<UuidAndTitleCache
<TaxonNode
>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1109 UUID classificationUuid
, Integer limit
, String pattern
, boolean searchForClassifications
) {
1110 return getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(
1111 classificationUuid
, limit
, pattern
, searchForClassifications
, false);