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
.io
.Serializable
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collection
;
15 import java
.util
.Collections
;
16 import java
.util
.Comparator
;
17 import java
.util
.HashSet
;
18 import java
.util
.List
;
20 import java
.util
.UUID
;
22 import org
.apache
.log4j
.Logger
;
23 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
24 import org
.springframework
.stereotype
.Service
;
25 import org
.springframework
.transaction
.annotation
.Transactional
;
27 import eu
.etaxonomy
.cdm
.api
.service
.UpdateResult
.Status
;
28 import eu
.etaxonomy
.cdm
.api
.service
.config
.NodeDeletionConfigurator
.ChildHandling
;
29 import eu
.etaxonomy
.cdm
.api
.service
.config
.SecundumForSubtreeConfigurator
;
30 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonDeletionConfigurator
;
31 import eu
.etaxonomy
.cdm
.api
.service
.config
.TaxonNodeDeletionConfigurator
;
32 import eu
.etaxonomy
.cdm
.api
.service
.dto
.CdmEntityIdentifier
;
33 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
34 import eu
.etaxonomy
.cdm
.api
.service
.pager
.PagerUtils
;
35 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
36 import eu
.etaxonomy
.cdm
.common
.monitor
.DefaultProgressMonitor
;
37 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
38 import eu
.etaxonomy
.cdm
.common
.monitor
.IRemotingProgressMonitor
;
39 import eu
.etaxonomy
.cdm
.common
.monitor
.RemotingProgressMonitorThread
;
40 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
41 import eu
.etaxonomy
.cdm
.hibernate
.HHH_9751_Util
;
42 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
43 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
44 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
45 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
46 import eu
.etaxonomy
.cdm
.model
.common
.TreeIndex
;
47 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
48 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
49 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
50 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.HomotypicGroupTaxonComparator
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.ITaxonTreeNode
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymType
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
59 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNodeAgentRelation
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
61 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.IBeanInitializer
;
62 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeDao
;
63 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonNodeFilterDao
;
64 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
65 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
69 * @created Apr 9, 2010
72 @Transactional(readOnly
= true)
73 public class TaxonNodeServiceImpl
extends AnnotatableServiceBase
<TaxonNode
, ITaxonNodeDao
> implements ITaxonNodeService
{
74 private static final Logger logger
= Logger
.getLogger(TaxonNodeServiceImpl
.class);
77 private IBeanInitializer defaultBeanInitializer
;
80 private ITaxonService taxonService
;
83 private IAgentService agentService
;
86 private ITaxonNodeFilterDao nodeFilterDao
;
89 IProgressMonitorService progressMonitorService
;
93 public List
<TaxonNode
> loadChildNodesOfTaxonNode(TaxonNode taxonNode
,
94 List
<String
> propertyPaths
, boolean recursive
, NodeSortMode sortMode
) {
96 getSession().refresh(taxonNode
);
97 List
<TaxonNode
> childNodes
;
98 if (recursive
== true){
99 childNodes
= dao
.listChildrenOf(taxonNode
, null, null, null, recursive
);
101 childNodes
= new ArrayList
<TaxonNode
>(taxonNode
.getChildNodes());
104 HHH_9751_Util
.removeAllNull(childNodes
);
106 if (sortMode
!= null){
107 Comparator
<TaxonNode
> comparator
= sortMode
.newComparator();
108 Collections
.sort(childNodes
, comparator
);
110 defaultBeanInitializer
.initializeAll(childNodes
, propertyPaths
);
118 public UuidAndTitleCache
<TaxonNode
> getParentUuidAndTitleCache(ITaxonTreeNode child
) {
119 UUID uuid
= child
.getUuid();
120 int id
= child
.getId();
121 UuidAndTitleCache
<TaxonNode
> uuidAndTitleCache
= new UuidAndTitleCache
<TaxonNode
>(uuid
, id
, null);
122 return getParentUuidAndTitleCache(uuidAndTitleCache
);
129 public UuidAndTitleCache
<TaxonNode
> getParentUuidAndTitleCache(UuidAndTitleCache
<TaxonNode
> child
) {
130 return dao
.getParentUuidAndTitleCache(child
);
137 public List
<UuidAndTitleCache
<TaxonNode
>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache
<TaxonNode
> parent
) {
138 return dao
.listChildNodesAsUuidAndTitleCache(parent
);
145 public List
<UuidAndTitleCache
<TaxonNode
>> getUuidAndTitleCache(Integer limit
, String pattern
, UUID classificationUuid
) {
146 return dao
.getUuidAndTitleCache(limit
, pattern
, classificationUuid
);
153 public List
<UuidAndTitleCache
<TaxonNode
>> listChildNodesAsUuidAndTitleCache(ITaxonTreeNode parent
) {
154 UUID uuid
= parent
.getUuid();
155 int id
= parent
.getId();
156 UuidAndTitleCache
<TaxonNode
> uuidAndTitleCache
= new UuidAndTitleCache
<TaxonNode
>(uuid
, id
, null);
157 return listChildNodesAsUuidAndTitleCache(uuidAndTitleCache
);
164 public Pager
<TaxonNodeDto
> pageChildNodesDTOs(UUID taxonNodeUuid
, boolean recursive
,
165 boolean doSynonyms
, NodeSortMode sortMode
,
166 Integer pageSize
, Integer pageIndex
) {
168 TaxonNode parentNode
= dao
.load(taxonNodeUuid
);
170 List
<CdmBase
> allRecords
= new ArrayList
<>();
173 List
<TaxonNode
> childNodes
= loadChildNodesOfTaxonNode(parentNode
, null, recursive
, sortMode
);
174 allRecords
.addAll(childNodes
);
176 //add synonyms if pager is not yet full synonyms
178 List
<Synonym
> synList
= new ArrayList
<>(parentNode
.getTaxon().getSynonyms());
179 Collections
.sort(synList
, new HomotypicGroupTaxonComparator(null));
182 allRecords
.addAll(synList
);
185 List
<TaxonNodeDto
> dtos
= new ArrayList
<>(pageSize
==null?
25:pageSize
);
186 Long totalCount
= Long
.valueOf(allRecords
.size());
188 TaxonName parentName
= null;
190 for(CdmBase record
: PagerUtils
.pageList(allRecords
, pageIndex
, pageSize
)) {
191 if (record
.isInstanceOf(TaxonNode
.class)){
192 dtos
.add(new TaxonNodeDto(CdmBase
.deproxy(record
, TaxonNode
.class)));
193 }else if (record
.isInstanceOf(Synonym
.class)){
194 Synonym synonym
= CdmBase
.deproxy(record
, Synonym
.class);
195 parentName
= parentName
== null? parentNode
.getTaxon().getName(): parentName
;
196 boolean isHomotypic
= synonym
.getName().isHomotypic(parentName
);
197 dtos
.add(new TaxonNodeDto(synonym
, isHomotypic
));
200 return new DefaultPagerImpl
<TaxonNodeDto
>(pageIndex
, totalCount
, pageSize
, dtos
);
204 public TaxonNodeDto
parentDto(UUID taxonNodeUuid
) {
205 TaxonNode taxonNode
= dao
.load(taxonNodeUuid
);
206 if(taxonNode
.getParent() != null) {
207 return new TaxonNodeDto(taxonNode
.getParent());
214 protected void setDao(ITaxonNodeDao dao
) {
219 @Transactional(readOnly
= false)
220 public DeleteResult
makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode
, TaxonNode newAcceptedTaxonNode
,
221 SynonymType synonymType
, Reference citation
, String citationMicroReference
) {
223 // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
224 // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
225 if (oldTaxonNode
== null || newAcceptedTaxonNode
== null || oldTaxonNode
.getTaxon().getName() == null){
226 throw new IllegalArgumentException("A mandatory parameter was null.");
229 if(oldTaxonNode
.equals(newAcceptedTaxonNode
)){
230 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
233 Classification classification
= oldTaxonNode
.getClassification();
234 Taxon oldTaxon
= HibernateProxyHelper
.deproxy(oldTaxonNode
.getTaxon());
235 Taxon newAcceptedTaxon
= (Taxon
)this.taxonService
.find(newAcceptedTaxonNode
.getTaxon().getUuid());
236 newAcceptedTaxon
= HibernateProxyHelper
.deproxy(newAcceptedTaxon
, Taxon
.class);
237 // Move oldTaxon to newTaxon
238 //TaxonName synonymName = oldTaxon.getName();
239 TaxonName newSynonymName
= CdmBase
.deproxy(oldTaxon
.getName());
240 HomotypicalGroup group
= CdmBase
.deproxy(newSynonymName
.getHomotypicalGroup());
241 if (synonymType
== null){
242 if (newSynonymName
.isHomotypic(newAcceptedTaxon
.getName())){
243 synonymType
= SynonymType
.HOMOTYPIC_SYNONYM_OF();
245 synonymType
= SynonymType
.HETEROTYPIC_SYNONYM_OF();
249 //set homotypic group
250 TaxonName newAcceptedTaxonName
= HibernateProxyHelper
.deproxy(newAcceptedTaxon
.getName(), TaxonName
.class);
251 newAcceptedTaxon
.setName(newAcceptedTaxonName
);
252 // Move Synonym Relations to new Taxon
253 Synonym newSynonym
= newAcceptedTaxon
.addSynonymName(newSynonymName
, citation
, citationMicroReference
,
255 // Move Synonyms to new Taxon
256 // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
257 List
<Synonym
> synonymsInHomotypicalGroup
= null;
259 //the synonyms of the homotypical group of the old taxon
260 if (synonymType
.equals(SynonymType
.HOMOTYPIC_SYNONYM_OF())){
261 synonymsInHomotypicalGroup
= oldTaxon
.getSynonymsInGroup(group
);
264 Set
<Synonym
> syns
= new HashSet
<>(oldTaxon
.getSynonyms());
265 for(Synonym synonym
: syns
){
267 if(synonym
.getHomotypicGroup()!= null
268 && synonym
.getHomotypicGroup().equals(newAcceptedTaxonName
.getHomotypicalGroup())) {
269 srt
= SynonymType
.HOMOTYPIC_SYNONYM_OF();
270 } else if(synonym
.getType() != null && synonym
.getType().equals(SynonymType
.HOMOTYPIC_SYNONYM_OF())) {
271 if (synonymType
.equals(SynonymType
.HOMOTYPIC_SYNONYM_OF())){
272 srt
= SynonymType
.HOMOTYPIC_SYNONYM_OF();
274 srt
= SynonymType
.HETEROTYPIC_SYNONYM_OF();
277 if (synonymsInHomotypicalGroup
!= null && synonymsInHomotypicalGroup
.contains(synonym
)){
278 srt
= SynonymType
.HOMOTYPIC_SYNONYM_OF();
280 srt
= synonym
.getType();
285 newAcceptedTaxon
.addSynonym(synonym
, srt
);
288 /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymType.HETEROTYPIC_SYNONYM_OF())){
289 homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
296 if(oldTaxonNode
.getChildNodes() != null && oldTaxonNode
.getChildNodes().size() != 0){
297 List
<TaxonNode
> childNodes
= new ArrayList
<TaxonNode
>();
298 for (TaxonNode childNode
: oldTaxonNode
.getChildNodes()){
299 childNodes
.add(childNode
);
301 for(TaxonNode childNode
:childNodes
){
302 newAcceptedTaxonNode
.addChildNode(childNode
, childNode
.getReference(), childNode
.getMicroReference()); // childNode.getSynonymToBeUsed()
306 //Move Taxon RelationShips to new Taxon
307 Set
<TaxonRelationship
> obsoleteTaxonRelationships
= new HashSet
<TaxonRelationship
>();
308 for(TaxonRelationship taxonRelationship
: oldTaxon
.getTaxonRelations()){
309 Taxon fromTaxon
= HibernateProxyHelper
.deproxy(taxonRelationship
.getFromTaxon());
310 Taxon toTaxon
= HibernateProxyHelper
.deproxy(taxonRelationship
.getToTaxon());
311 if (fromTaxon
== oldTaxon
){
312 newAcceptedTaxon
.addTaxonRelation(taxonRelationship
.getToTaxon(), taxonRelationship
.getType(),
313 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
315 }else if(toTaxon
== oldTaxon
){
316 fromTaxon
.addTaxonRelation(newAcceptedTaxon
, taxonRelationship
.getType(),
317 taxonRelationship
.getCitation(), taxonRelationship
.getCitationMicroReference());
318 taxonService
.saveOrUpdate(fromTaxon
);
321 logger
.warn("Taxon is not part of its own Taxonrelationship");
323 // Remove old relationships
325 fromTaxon
.removeTaxonRelation(taxonRelationship
);
326 toTaxon
.removeTaxonRelation(taxonRelationship
);
327 taxonRelationship
.setToTaxon(null);
328 taxonRelationship
.setFromTaxon(null);
332 //Move descriptions to new taxon
333 List
<TaxonDescription
> descriptions
= new ArrayList
<TaxonDescription
>( oldTaxon
.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
334 for(TaxonDescription description
: descriptions
){
335 String message
= "Description copied from former accepted taxon: %s (Old title: %s)";
336 message
= String
.format(message
, oldTaxon
.getTitleCache(), description
.getTitleCache());
337 description
.setTitleCache(message
, true);
338 //oldTaxon.removeDescription(description, false);
339 newAcceptedTaxon
.addDescription(description
);
341 oldTaxon
.clearDescriptions();
343 taxonService
.saveOrUpdate(newAcceptedTaxon
);
345 taxonService
.saveOrUpdate(oldTaxon
);
346 taxonService
.getSession().flush();
348 TaxonDeletionConfigurator conf
= new TaxonDeletionConfigurator();
349 conf
.setDeleteSynonymsIfPossible(false);
350 conf
.setDeleteNameIfPossible(false);
351 DeleteResult result
= taxonService
.isDeletable(oldTaxon
.getUuid(), conf
);
355 result
= taxonService
.deleteTaxon(oldTaxon
.getUuid(), conf
, classification
.getUuid());
358 result
.setStatus(Status
.OK
);
359 TaxonNodeDeletionConfigurator config
= new TaxonNodeDeletionConfigurator();
360 config
.setDeleteElement(false);
361 conf
.setTaxonNodeConfig(config
);
362 result
.includeResult(deleteTaxonNode(oldTaxonNode
, conf
));
365 result
.addUpdatedObject(newAcceptedTaxon
);
368 //oldTaxonNode.delete();
374 @Transactional(readOnly
= false)
375 public UpdateResult
makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid
,
376 UUID newAcceptedTaxonNodeUUID
,
377 SynonymType synonymType
,
379 String citationMicroReference
) {
381 TaxonNode oldTaxonNode
= dao
.load(oldTaxonNodeUuid
);
382 TaxonNode oldTaxonParentNode
= oldTaxonNode
.getParent();
383 TaxonNode newTaxonNode
= dao
.load(newAcceptedTaxonNodeUUID
);
385 UpdateResult result
= makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode
,
389 citationMicroReference
);
390 result
.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode
.getId(), TaxonNode
.class));
391 result
.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode
.getId(), TaxonNode
.class));
392 result
.setCdmEntity(oldTaxonParentNode
);
397 @Transactional(readOnly
= false)
398 public DeleteResult
deleteTaxonNodes(List
<TaxonNode
> list
, TaxonDeletionConfigurator config
) {
401 config
= new TaxonDeletionConfigurator();
403 DeleteResult result
= new DeleteResult();
404 List
<UUID
> deletedUUIDs
= new ArrayList
<UUID
>();
405 Classification classification
= null;
406 List
<TaxonNode
> taxonNodes
= new ArrayList
<TaxonNode
>(list
);
407 for (TaxonNode treeNode
:taxonNodes
){
408 if (treeNode
!= null){
411 taxonNode
= HibernateProxyHelper
.deproxy(treeNode
, TaxonNode
.class);
412 TaxonNode parent
= taxonNode
.getParent();
413 //check whether the node has children or the children are already deleted
414 if(taxonNode
.hasChildNodes()) {
415 List
<TaxonNode
> children
= new ArrayList
<TaxonNode
> ();
416 List
<TaxonNode
> childNodesList
= taxonNode
.getChildNodes();
417 children
.addAll(childNodesList
);
418 int compare
= config
.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling
.DELETE
);
419 boolean childHandling
= (compare
== 0)?
true: false;
421 boolean changeDeleteTaxon
= false;
422 if (!config
.getTaxonNodeConfig().isDeleteTaxon()){
423 config
.getTaxonNodeConfig().setDeleteTaxon(true);
424 changeDeleteTaxon
= true;
426 DeleteResult resultNodes
= deleteTaxonNodes(children
, config
);
427 if (!resultNodes
.isOk()){
428 result
.addExceptions(resultNodes
.getExceptions());
429 result
.setStatus(resultNodes
.getStatus());
431 if (changeDeleteTaxon
){
432 config
.getTaxonNodeConfig().setDeleteTaxon(false);
436 //move the children to the parent
438 for (TaxonNode child
: childNodesList
){
439 parent
.addChildNode(child
, child
.getReference(), child
.getMicroReference());
445 classification
= taxonNode
.getClassification();
447 if (classification
.getRootNode().equals(taxonNode
)){
448 classification
.removeRootNode();
449 classification
= null;
450 }else if (classification
.getChildNodes().contains(taxonNode
)){
451 Taxon taxon
= taxonNode
.getTaxon();
452 classification
.deleteChildNode(taxonNode
);
457 if (config
.getTaxonNodeConfig().isDeleteTaxon()){
458 taxonService
.saveOrUpdate(taxon
);
459 saveOrUpdate(taxonNode
);
461 TaxonDeletionConfigurator configNew
= new TaxonDeletionConfigurator();
462 DeleteResult resultTaxon
= taxonService
.deleteTaxon(taxon
.getUuid(), configNew
, classification
.getUuid());
463 if (!resultTaxon
.isOk()){
464 result
.addExceptions(resultTaxon
.getExceptions());
465 result
.setStatus(resultTaxon
.getStatus());
470 classification
= null;
473 classification
= null;
474 Taxon taxon
= taxonNode
.getTaxon();
475 taxon
= HibernateProxyHelper
.deproxy(taxon
, Taxon
.class);
477 taxon
.removeTaxonNode(taxonNode
);
478 if (config
.getTaxonNodeConfig().isDeleteTaxon()){
479 TaxonDeletionConfigurator configNew
= new TaxonDeletionConfigurator();
480 saveOrUpdate(taxonNode
);
481 taxonService
.saveOrUpdate(taxon
);
482 DeleteResult resultTaxon
= taxonService
.deleteTaxon(taxon
.getUuid(), configNew
, null);
484 if (!resultTaxon
.isOk()){
485 result
.addExceptions(resultTaxon
.getExceptions());
486 result
.setStatus(resultTaxon
.getStatus());
493 result
.addUpdatedObject(parent
);
494 if(result
.getCdmEntity() == null){
495 result
.setCdmEntity(taxonNode
);
497 UUID uuid
= dao
.delete(taxonNode
);
498 logger
.debug("Deleted node " +uuid
.toString());
502 /*if (classification != null){
503 result.addUpdatedObject(classification);
504 DeleteResult resultClassification = classService.delete(classification);
505 if (!resultClassification.isOk()){
506 result.addExceptions(resultClassification.getExceptions());
507 result.setStatus(resultClassification.getStatus());
515 @Transactional(readOnly
= false)
516 public DeleteResult
deleteTaxonNodes(Collection
<UUID
> nodeUuids
, TaxonDeletionConfigurator config
) {
517 List
<TaxonNode
> nodes
= new ArrayList
<TaxonNode
>();
518 for(UUID nodeUuid
: nodeUuids
) {
519 nodes
.add(dao
.load(nodeUuid
));
521 return deleteTaxonNodes(nodes
, config
);
526 @Transactional(readOnly
= false)
527 public DeleteResult
deleteTaxonNode(UUID nodeUUID
, TaxonDeletionConfigurator config
) {
529 TaxonNode node
= HibernateProxyHelper
.deproxy(dao
.load(nodeUUID
), TaxonNode
.class);
530 return deleteTaxonNode(node
, config
);
534 @Transactional(readOnly
= false)
535 public DeleteResult
deleteTaxonNode(TaxonNode node
, TaxonDeletionConfigurator config
) {
536 DeleteResult result
= new DeleteResult();
539 result
.addException(new Exception("The TaxonNode was already deleted."));
544 taxon
= HibernateProxyHelper
.deproxy(node
.getTaxon());
545 }catch(NullPointerException e
){
547 result
.addException(new Exception("The Taxon was already deleted."));
550 TaxonNode parent
= HibernateProxyHelper
.deproxy(node
.getParent(), TaxonNode
.class);
552 config
= new TaxonDeletionConfigurator();
556 if (config
.getTaxonNodeConfig().getChildHandling().equals(ChildHandling
.MOVE_TO_PARENT
)){
557 Object
[] children
= node
.getChildNodes().toArray();
559 for (Object child
: children
){
560 childNode
= (TaxonNode
) child
;
561 parent
.addChildNode(childNode
, childNode
.getReference(), childNode
.getMicroReference());
564 deleteTaxonNodes(node
.getChildNodes(), config
);
568 if (config
.getTaxonNodeConfig().isDeleteTaxon() && (config
.isDeleteInAllClassifications() || taxon
.getTaxonNodes().size() == 1)){
569 result
= taxonService
.deleteTaxon(taxon
.getUuid(), config
, node
.getClassification().getUuid());
570 result
.addUpdatedObject(parent
);
575 result
.addUpdatedObject(taxon
);
578 result
.setCdmEntity(node
);
579 boolean success
= taxon
.removeTaxonNode(node
);
580 dao
.saveOrUpdate(parent
);
581 taxonService
.saveOrUpdate(taxon
);
582 result
.addUpdatedObject(parent
);
585 result
.setStatus(Status
.OK
);
586 parent
= HibernateProxyHelper
.deproxy(parent
, TaxonNode
.class);
587 int index
= parent
.getChildNodes().indexOf(node
);
589 parent
.removeChild(index
);
591 if (!dao
.delete(node
, config
.getTaxonNodeConfig().getChildHandling().equals(ChildHandling
.DELETE
)).equals(null)){
598 if (dao
.findByUuid(node
.getUuid()) != null){
600 result
.addException(new Exception("The node can not be removed from the taxon."));
608 public List
<TaxonNode
> listAllNodesForClassification(Classification classification
, Integer start
, Integer end
) {
609 return dao
.getTaxonOfAcceptedTaxaByClassification(classification
, start
, end
);
613 public int countAllNodesForClassification(Classification classification
) {
614 return dao
.countTaxonOfAcceptedTaxaByClassification(classification
);
619 public UpdateResult
moveTaxonNode(UUID taxonNodeUuid
, UUID targetNodeUuid
, int movingType
){
620 TaxonNode taxonNode
= HibernateProxyHelper
.deproxy(dao
.load(taxonNodeUuid
), TaxonNode
.class);
621 TaxonNode targetNode
= HibernateProxyHelper
.deproxy(dao
.load(targetNodeUuid
), TaxonNode
.class);
622 return moveTaxonNode(taxonNode
, targetNode
, movingType
);
627 public UpdateResult
moveTaxonNode(TaxonNode taxonNode
, TaxonNode newParent
, int movingType
){
628 UpdateResult result
= new UpdateResult();
630 TaxonNode parentParent
= HibernateProxyHelper
.deproxy(newParent
.getParent(), TaxonNode
.class);
631 TaxonNode oldParent
= HibernateProxyHelper
.deproxy(taxonNode
.getParent(), TaxonNode
.class);
632 Integer sortIndex
= -1;
633 if (movingType
== 0){
635 }else if (movingType
== 1){
636 sortIndex
= newParent
.getSortIndex();
637 newParent
= parentParent
;
638 } else if (movingType
== 2){
639 sortIndex
= newParent
.getSortIndex() +1;
640 newParent
= parentParent
;
643 result
.addException(new Exception("The moving type "+ movingType
+" is not supported."));
647 taxonNode
= newParent
.addChildNode(taxonNode
, sortIndex
, taxonNode
.getReference(), taxonNode
.getMicroReference());
648 result
.addUpdatedObject(newParent
);
649 result
.addUpdatedObject(oldParent
);
650 result
.setCdmEntity(taxonNode
);
652 dao
.saveOrUpdate(taxonNode
);
653 dao
.saveOrUpdate(oldParent
);
662 public UpdateResult
moveTaxonNodes(Set
<UUID
> taxonNodeUuids
, UUID newParentNodeUuid
, int movingType
){
663 UpdateResult result
= new UpdateResult();
664 TaxonNode targetNode
= dao
.load(newParentNodeUuid
);
665 for (UUID taxonNodeUuid
: taxonNodeUuids
){
666 TaxonNode taxonNode
= dao
.load(taxonNodeUuid
);
667 result
.includeResult(moveTaxonNode(taxonNode
,targetNode
, movingType
));
673 public Pager
<TaxonNodeAgentRelation
> pageTaxonNodeAgentRelations(UUID taxonUuid
, UUID classificationUuid
,
674 UUID agentUuid
, UUID rankUuid
, UUID relTypeUuid
, Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) {
677 List
<TaxonNodeAgentRelation
> records
= null;
679 long count
= dao
.countTaxonNodeAgentRelations(taxonUuid
, classificationUuid
, agentUuid
, rankUuid
, relTypeUuid
);
680 if(PagerUtils
.hasResultsInRange(count
, pageIndex
, pageSize
)) {
681 records
= dao
.listTaxonNodeAgentRelations(taxonUuid
, classificationUuid
,
682 agentUuid
, rankUuid
, relTypeUuid
, PagerUtils
.startFor(pageSize
, pageIndex
), PagerUtils
.limitFor(pageSize
), propertyPaths
);
685 Pager
<TaxonNodeAgentRelation
> pager
= new DefaultPagerImpl
<TaxonNodeAgentRelation
>(pageIndex
, count
, pageSize
, records
);
691 public UpdateResult
createNewTaxonNode(UUID parentNodeUuid
, Taxon newTaxon
, Reference ref
, String microref
){
692 UpdateResult result
= new UpdateResult();
694 UUID taxonUUID
= taxonService
.saveOrUpdate(newTaxon
);
695 newTaxon
= (Taxon
) taxonService
.load(taxonUUID
);
697 TaxonNode parent
= dao
.load(parentNodeUuid
);
698 TaxonNode child
= null;
700 child
= parent
.addChildTaxon(newTaxon
, parent
.getReference(), parent
.getMicroReference());
702 result
.addException(e
);
706 // child = dao.save(child);
708 dao
.saveOrUpdate(parent
);
709 result
.addUpdatedObject(parent
);
711 result
.setCdmEntity(child
);
718 public UpdateResult
createNewTaxonNode(UUID parentNodeUuid
, UUID taxonUuid
, Reference ref
, String microref
){
719 UpdateResult result
= new UpdateResult();
720 TaxonNode parent
= dao
.load(parentNodeUuid
);
721 Taxon taxon
= (Taxon
) taxonService
.load(taxonUuid
);
722 TaxonNode child
= null;
724 child
= parent
.addChildTaxon(taxon
, parent
.getReference(), parent
.getMicroReference());
726 result
.addException(e
);
730 // child = dao.save(child);
732 dao
.saveOrUpdate(child
);
733 result
.addUpdatedObject(parent
);
735 result
.setCdmEntity(child
);
743 public UpdateResult
addTaxonNodeAgentRelation(UUID taxonNodeUUID
, UUID agentUUID
, DefinedTerm relationshipType
){
744 UpdateResult result
= new UpdateResult();
745 TaxonNode node
= dao
.load(taxonNodeUUID
);
746 TeamOrPersonBase agent
= (TeamOrPersonBase
) agentService
.load(agentUUID
);
747 node
.addAgentRelation(relationshipType
, agent
);
749 dao
.merge(node
, true);
750 }catch (Exception e
){
752 result
.addException(e
);
754 result
.setCdmEntity(node
);
760 public UpdateResult
setSecundumForSubtree(SecundumForSubtreeConfigurator config
) {
761 UpdateResult result
= new UpdateResult();
762 // IProgressMonitor monitor = config.getMonitor();
763 IProgressMonitor monitor
= config
.getMonitor();
764 if (monitor
== null){
765 monitor
= DefaultProgressMonitor
.NewInstance();
768 monitor
.beginTask("Update Secundum Reference", 100);
769 if (config
.getSubtreeUuid() == null){
771 result
.addException(new NullPointerException("No subtree given"));
775 TaxonNode subTree
= load(config
.getSubtreeUuid());
776 if (subTree
== null){
778 result
.addException(new NullPointerException("Subtree does not exist"));
782 TreeIndex subTreeIndex
= TreeIndex
.NewInstance(subTree
.treeIndex());
784 //Reference ref = config.getNewSecundum();
785 if (config
.isIncludeAcceptedTaxa()){
786 monitor
.subTask("Update Accepted Taxa");
787 Set
<TaxonBase
> updatedTaxa
= dao
.setSecundumForSubtreeAcceptedTaxa(subTreeIndex
, config
.getNewSecundum(), config
.isOverwriteExistingAccepted(), config
.isIncludeSharedTaxa(), config
.isEmptySecundumDetail());
788 // taxonService.saveOrUpdate(updatedTaxa);
790 result
.addUpdatedObjects(updatedTaxa
);
792 if (config
.isIncludeSynonyms()){
793 monitor
.subTask("Update Synonyms");
794 Set
<TaxonBase
> updatedSynonyms
= dao
.setSecundumForSubtreeSynonyms(subTreeIndex
, config
.getNewSecundum(), config
.isOverwriteExistingSynonyms(), config
.isIncludeSharedTaxa() , config
.isEmptySecundumDetail());
795 // taxonService.saveOrUpdate(updatedSynonyms);
797 result
.addUpdatedObjects(updatedSynonyms
);
809 public UpdateResult
setPublishForSubtree(UUID subtreeUuid
, boolean publish
, boolean includeAcceptedTaxa
,
810 boolean includeSynonyms
, boolean includeSharedTaxa
, IProgressMonitor monitor
) {
811 UpdateResult result
= new UpdateResult();
812 // IProgressMonitor monitor = config.getMonitor();
813 if (monitor
== null){
814 monitor
= DefaultProgressMonitor
.NewInstance();
816 monitor
.beginTask("Update publish flag", 100);
817 if (subtreeUuid
== null){
819 result
.addException(new NullPointerException("No subtree given"));
823 TaxonNode subTree
= find(subtreeUuid
);
824 if (subTree
== null){
826 result
.addException(new NullPointerException("Subtree does not exist"));
830 TreeIndex subTreeIndex
= TreeIndex
.NewInstance(subTree
.treeIndex());
832 //Reference ref = config.getNewSecundum();
833 if (includeAcceptedTaxa
){
834 monitor
.subTask("Update Accepted Taxa");
835 Set
<Taxon
> updatedTaxa
= dao
.setPublishForSubtreeAcceptedTaxa(subTreeIndex
, publish
, includeSharedTaxa
);
836 result
.addUpdatedObjects(updatedTaxa
);
838 if (includeSynonyms
){
839 monitor
.subTask("Update Synonyms");
840 Set
<Synonym
> updatedSynonyms
= dao
.setPublishForSubtreeSynonyms(subTreeIndex
, publish
, includeSharedTaxa
);
841 result
.addUpdatedObjects(updatedSynonyms
);
849 public long count(TaxonNodeFilter filter
){
850 return nodeFilterDao
.count(filter
);
854 public List
<UUID
> uuidList(TaxonNodeFilter filter
){
855 return nodeFilterDao
.listUuids(filter
);
859 public List
<Integer
> idList(TaxonNodeFilter filter
){
860 return nodeFilterDao
.idList(filter
);
864 public UUID
monitSetSecundum(final SecundumForSubtreeConfigurator configurator
) {
865 RemotingProgressMonitorThread monitorThread
= new RemotingProgressMonitorThread() {
867 public Serializable
doRun(IRemotingProgressMonitor monitor
) {
868 configurator
.setMonitor(monitor
);
869 UpdateResult result
= setSecundumForSubtree(configurator
);
873 UUID uuid
= progressMonitorService
.registerNewRemotingMonitor(monitorThread
);
874 monitorThread
.setPriority(3);
875 monitorThread
.start();