smaller changes in ForSubtreeConfigurator
[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.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;
19 import java.util.Set;
20 import java.util.UUID;
21
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;
26
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;
66
67 /**
68 * @author n.hoffmann
69 * @created Apr 9, 2010
70 */
71 @Service
72 @Transactional(readOnly = true)
73 public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{
74 private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
75
76 @Autowired
77 private IBeanInitializer defaultBeanInitializer;
78
79 @Autowired
80 private ITaxonService taxonService;
81
82 @Autowired
83 private IAgentService agentService;
84
85 @Autowired
86 private ITaxonNodeFilterDao nodeFilterDao;
87
88 @Autowired
89 IProgressMonitorService progressMonitorService;
90
91
92 @Override
93 public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
94 List<String> propertyPaths, boolean recursive, NodeSortMode sortMode) {
95
96 getSession().refresh(taxonNode);
97 List<TaxonNode> childNodes;
98 if (recursive == true){
99 childNodes = dao.listChildrenOf(taxonNode, null, null, null, recursive);
100 }else{
101 childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
102 }
103
104 HHH_9751_Util.removeAllNull(childNodes);
105
106 if (sortMode != null){
107 Comparator<TaxonNode> comparator = sortMode.newComparator();
108 Collections.sort(childNodes, comparator);
109 }
110 defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
111 return childNodes;
112 }
113
114 /**
115 * {@inheritDoc}
116 */
117 @Override
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);
123 }
124
125 /**
126 * {@inheritDoc}
127 */
128 @Override
129 public UuidAndTitleCache<TaxonNode> getParentUuidAndTitleCache(UuidAndTitleCache<TaxonNode> child) {
130 return dao.getParentUuidAndTitleCache(child);
131 }
132
133 /**
134 * {@inheritDoc}
135 */
136 @Override
137 public List<UuidAndTitleCache<TaxonNode>> listChildNodesAsUuidAndTitleCache(UuidAndTitleCache<TaxonNode> parent) {
138 return dao.listChildNodesAsUuidAndTitleCache(parent);
139 }
140
141 /**
142 * {@inheritDoc}
143 */
144 @Override
145 public List<UuidAndTitleCache<TaxonNode>> getUuidAndTitleCache(Integer limit, String pattern, UUID classificationUuid) {
146 return dao.getUuidAndTitleCache(limit, pattern, classificationUuid);
147 }
148
149 /**
150 * {@inheritDoc}
151 */
152 @Override
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);
158 }
159
160 /**
161 * {@inheritDoc}
162 */
163 @Override
164 public Pager<TaxonNodeDto> pageChildNodesDTOs(UUID taxonNodeUuid, boolean recursive,
165 boolean doSynonyms, NodeSortMode sortMode,
166 Integer pageSize, Integer pageIndex) {
167
168 TaxonNode parentNode = dao.load(taxonNodeUuid);
169
170 List<CdmBase> allRecords = new ArrayList<>();
171
172 //acceptedTaxa
173 List<TaxonNode> childNodes = loadChildNodesOfTaxonNode(parentNode, null, recursive, sortMode);
174 allRecords.addAll(childNodes);
175
176 //add synonyms if pager is not yet full synonyms
177 if (doSynonyms){
178 List<Synonym> synList = new ArrayList<>(parentNode.getTaxon().getSynonyms());
179 Collections.sort(synList, new HomotypicGroupTaxonComparator(null));
180 //TODO: test sorting
181
182 allRecords.addAll(synList);
183 }
184
185 List<TaxonNodeDto> dtos = new ArrayList<>(pageSize==null?25:pageSize);
186 Long totalCount = Long.valueOf(allRecords.size());
187
188 TaxonName parentName = null;
189
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));
198 }
199 }
200 return new DefaultPagerImpl<TaxonNodeDto>(pageIndex, totalCount, pageSize , dtos);
201 }
202
203 @Override
204 public TaxonNodeDto parentDto(UUID taxonNodeUuid) {
205 TaxonNode taxonNode = dao.load(taxonNodeUuid);
206 if(taxonNode.getParent() != null) {
207 return new TaxonNodeDto(taxonNode.getParent());
208 }
209 return null;
210 }
211
212 @Override
213 @Autowired
214 protected void setDao(ITaxonNodeDao dao) {
215 this.dao = dao;
216 }
217
218 @Override
219 @Transactional(readOnly = false)
220 public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode,
221 SynonymType synonymType, Reference citation, String citationMicroReference) {
222
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.");
227 }
228
229 if(oldTaxonNode.equals(newAcceptedTaxonNode)){
230 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
231 }
232
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();
244 }else{
245 synonymType = SynonymType.HETEROTYPIC_SYNONYM_OF();
246 }
247 }
248
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,
254 synonymType);
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;
258
259 //the synonyms of the homotypical group of the old taxon
260 if (synonymType.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())){
261 synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
262 }
263
264 Set<Synonym> syns = new HashSet<>(oldTaxon.getSynonyms());
265 for(Synonym synonym : syns){
266 SynonymType srt;
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();
273 } else{
274 srt = SynonymType.HETEROTYPIC_SYNONYM_OF();
275 }
276 } else {
277 if (synonymsInHomotypicalGroup != null && synonymsInHomotypicalGroup.contains(synonym)){
278 srt = SynonymType.HOMOTYPIC_SYNONYM_OF();
279 }else{
280 srt = synonym.getType();
281 }
282
283 }
284
285 newAcceptedTaxon.addSynonym(synonym, srt);
286
287
288 /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymType.HETEROTYPIC_SYNONYM_OF())){
289 homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
290 }*/
291
292 }
293
294
295 // CHILD NODES
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);
300 }
301 for(TaxonNode childNode :childNodes){
302 newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
303 }
304 }
305
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());
314
315 }else if(toTaxon == oldTaxon){
316 fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
317 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
318 taxonService.saveOrUpdate(fromTaxon);
319
320 }else{
321 logger.warn("Taxon is not part of its own Taxonrelationship");
322 }
323 // Remove old relationships
324
325 fromTaxon.removeTaxonRelation(taxonRelationship);
326 toTaxon.removeTaxonRelation(taxonRelationship);
327 taxonRelationship.setToTaxon(null);
328 taxonRelationship.setFromTaxon(null);
329 }
330
331
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);
340 }
341 oldTaxon.clearDescriptions();
342
343 taxonService.saveOrUpdate(newAcceptedTaxon);
344
345 taxonService.saveOrUpdate(oldTaxon);
346 taxonService.getSession().flush();
347
348 TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
349 conf.setDeleteSynonymsIfPossible(false);
350 conf.setDeleteNameIfPossible(false);
351 DeleteResult result = taxonService.isDeletable(oldTaxon.getUuid(), conf);
352
353
354 if (result.isOk()){
355 result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());
356
357 }else{
358 result.setStatus(Status.OK);
359 TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
360 config.setDeleteElement(false);
361 conf.setTaxonNodeConfig(config);
362 result.includeResult(deleteTaxonNode(oldTaxonNode, conf));
363 }
364
365 result.addUpdatedObject(newAcceptedTaxon);
366
367
368 //oldTaxonNode.delete();
369 return result;
370 }
371
372
373 @Override
374 @Transactional(readOnly = false)
375 public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,
376 UUID newAcceptedTaxonNodeUUID,
377 SynonymType synonymType,
378 Reference citation,
379 String citationMicroReference) {
380
381 TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
382 TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
383 TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);
384
385 UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,
386 newTaxonNode,
387 synonymType,
388 citation,
389 citationMicroReference);
390 result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
391 result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
392 result.setCdmEntity(oldTaxonParentNode);
393 return result;
394 }
395
396 @Override
397 @Transactional(readOnly = false)
398 public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {
399
400 if (config == null){
401 config = new TaxonDeletionConfigurator();
402 }
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){
409
410 TaxonNode taxonNode;
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;
420 if (childHandling){
421 boolean changeDeleteTaxon = false;
422 if (!config.getTaxonNodeConfig().isDeleteTaxon()){
423 config.getTaxonNodeConfig().setDeleteTaxon(true);
424 changeDeleteTaxon = true;
425 }
426 DeleteResult resultNodes = deleteTaxonNodes(children, config);
427 if (!resultNodes.isOk()){
428 result.addExceptions(resultNodes.getExceptions());
429 result.setStatus(resultNodes.getStatus());
430 }
431 if (changeDeleteTaxon){
432 config.getTaxonNodeConfig().setDeleteTaxon(false);
433 }
434
435 } else {
436 //move the children to the parent
437
438 for (TaxonNode child: childNodesList){
439 parent.addChildNode(child, child.getReference(), child.getMicroReference());
440 }
441
442 }
443 }
444
445 classification = taxonNode.getClassification();
446
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);
453
454 //node is rootNode
455 if (taxon != null){
456
457 if (config.getTaxonNodeConfig().isDeleteTaxon()){
458 taxonService.saveOrUpdate(taxon);
459 saveOrUpdate(taxonNode);
460
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());
466 }
467
468 }
469 }
470 classification = null;
471
472 } else {
473 classification = null;
474 Taxon taxon = taxonNode.getTaxon();
475 taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
476 if (taxon != null){
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);
483
484 if (!resultTaxon.isOk()){
485 result.addExceptions(resultTaxon.getExceptions());
486 result.setStatus(resultTaxon.getStatus());
487 }
488 }
489 }
490
491 }
492
493 result.addUpdatedObject(parent);
494 if(result.getCdmEntity() == null){
495 result.setCdmEntity(taxonNode);
496 }
497 UUID uuid = dao.delete(taxonNode);
498 logger.debug("Deleted node " +uuid.toString());
499
500 }
501 }
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());
508 }
509 }*/
510 return result;
511 }
512
513
514 @Override
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));
520 }
521 return deleteTaxonNodes(nodes, config);
522 }
523
524
525 @Override
526 @Transactional(readOnly = false)
527 public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
528
529 TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);
530 return deleteTaxonNode(node, config);
531 }
532
533 @Override
534 @Transactional(readOnly = false)
535 public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
536 DeleteResult result = new DeleteResult();
537 if (node == null){
538 result.setAbort();
539 result.addException(new Exception("The TaxonNode was already deleted."));
540 return result;
541 }
542 Taxon taxon = null;
543 try{
544 taxon = HibernateProxyHelper.deproxy(node.getTaxon());
545 }catch(NullPointerException e){
546 result.setAbort();
547 result.addException(new Exception("The Taxon was already deleted."));
548
549 }
550 TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);
551 if (config == null){
552 config = new TaxonDeletionConfigurator();
553 }
554
555
556 if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.MOVE_TO_PARENT)){
557 Object[] children = node.getChildNodes().toArray();
558 TaxonNode childNode;
559 for (Object child: children){
560 childNode = (TaxonNode) child;
561 parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());
562 }
563 }else{
564 deleteTaxonNodes(node.getChildNodes(), config);
565 }
566
567 if (taxon != null){
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);
571 if (result.isOk()){
572 return result;
573 }
574 } else {
575 result.addUpdatedObject(taxon);
576 }
577 }
578 result.setCdmEntity(node);
579 boolean success = taxon.removeTaxonNode(node);
580 dao.saveOrUpdate(parent);
581 taxonService.saveOrUpdate(taxon);
582 result.addUpdatedObject(parent);
583
584 if (success){
585 result.setStatus(Status.OK);
586 parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);
587 int index = parent.getChildNodes().indexOf(node);
588 if (index > -1){
589 parent.removeChild(index);
590 }
591 if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)).equals(null)){
592 return result;
593 } else {
594 result.setError();
595 return result;
596 }
597 }else{
598 if (dao.findByUuid(node.getUuid()) != null){
599 result.setError();
600 result.addException(new Exception("The node can not be removed from the taxon."));
601 }
602 return result;
603 }
604 }
605
606
607 @Override
608 public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
609 return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
610 }
611
612 @Override
613 public int countAllNodesForClassification(Classification classification) {
614 return dao.countTaxonOfAcceptedTaxaByClassification(classification);
615 }
616
617 @Override
618 @Transactional
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);
623 }
624
625 @Override
626 @Transactional
627 public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, int movingType){
628 UpdateResult result = new UpdateResult();
629
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){
634 sortIndex = 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;
641 } else{
642 result.setAbort();
643 result.addException(new Exception("The moving type "+ movingType +" is not supported."));
644 }
645
646
647 taxonNode = newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(), taxonNode.getMicroReference());
648 result.addUpdatedObject(newParent);
649 result.addUpdatedObject(oldParent);
650 result.setCdmEntity(taxonNode);
651
652 dao.saveOrUpdate(taxonNode);
653 dao.saveOrUpdate(oldParent);
654
655 return result;
656 }
657
658
659
660 @Override
661 @Transactional
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));
668 }
669 return result;
670 }
671
672 @Override
673 public Pager<TaxonNodeAgentRelation> pageTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
674 UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
675
676
677 List<TaxonNodeAgentRelation> records = null;
678
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);
683 }
684
685 Pager<TaxonNodeAgentRelation> pager = new DefaultPagerImpl<TaxonNodeAgentRelation>(pageIndex, count, pageSize, records);
686 return pager;
687 }
688
689 @Override
690 @Transactional
691 public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){
692 UpdateResult result = new UpdateResult();
693
694 UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
695 newTaxon = (Taxon) taxonService.load(taxonUUID);
696
697 TaxonNode parent = dao.load(parentNodeUuid);
698 TaxonNode child = null;
699 try{
700 child = parent.addChildTaxon(newTaxon, parent.getReference(), parent.getMicroReference());
701 }catch(Exception e){
702 result.addException(e);
703 result.setError();
704 return result;
705 }
706 // child = dao.save(child);
707
708 dao.saveOrUpdate(parent);
709 result.addUpdatedObject(parent);
710 if (child != null){
711 result.setCdmEntity(child);
712 }
713 return result;
714
715 }
716 @Override
717 @Transactional
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;
723 try{
724 child = parent.addChildTaxon(taxon, parent.getReference(), parent.getMicroReference());
725 }catch(Exception e){
726 result.addException(e);
727 result.setError();
728 return result;
729 }
730 // child = dao.save(child);
731
732 dao.saveOrUpdate(child);
733 result.addUpdatedObject(parent);
734 if (child != null){
735 result.setCdmEntity(child);
736 }
737 return result;
738
739 }
740
741 @Override
742 @Transactional
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);
748 try{
749 dao.merge(node, true);
750 }catch (Exception e){
751 result.setError();
752 result.addException(e);
753 }
754 result.setCdmEntity(node);
755 return result;
756 }
757
758 @Override
759 @Transactional
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();
766 }
767
768 monitor.beginTask("Update Secundum Reference", 100);
769 if (config.getSubtreeUuid() == null){
770 result.setError();
771 result.addException(new NullPointerException("No subtree given"));
772 monitor.done();
773 return result;
774 }
775 TaxonNode subTree = load(config.getSubtreeUuid());
776 if (subTree == null){
777 result.setError();
778 result.addException(new NullPointerException("Subtree does not exist"));
779 monitor.done();
780 return result;
781 }
782 TreeIndex subTreeIndex = TreeIndex.NewInstance(subTree.treeIndex());
783
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);
789
790 result.addUpdatedObjects(updatedTaxa);
791 }
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);
796
797 result.addUpdatedObjects(updatedSynonyms);
798 }
799
800 monitor.done();
801 return result;
802 }
803
804
805 /**
806 * {@inheritDoc}
807 */
808 @Override
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();
815 }
816 monitor.beginTask("Update publish flag", 100);
817 if (subtreeUuid == null){
818 result.setError();
819 result.addException(new NullPointerException("No subtree given"));
820 monitor.done();
821 return result;
822 }
823 TaxonNode subTree = find(subtreeUuid);
824 if (subTree == null){
825 result.setError();
826 result.addException(new NullPointerException("Subtree does not exist"));
827 monitor.done();
828 return result;
829 }
830 TreeIndex subTreeIndex = TreeIndex.NewInstance(subTree.treeIndex());
831
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);
837 }
838 if (includeSynonyms){
839 monitor.subTask("Update Synonyms");
840 Set<Synonym> updatedSynonyms = dao.setPublishForSubtreeSynonyms(subTreeIndex, publish, includeSharedTaxa);
841 result.addUpdatedObjects(updatedSynonyms);
842 }
843 monitor.done();
844 return result;
845 }
846
847
848 @Override
849 public long count(TaxonNodeFilter filter){
850 return nodeFilterDao.count(filter);
851 }
852
853 @Override
854 public List<UUID> uuidList(TaxonNodeFilter filter){
855 return nodeFilterDao.listUuids(filter);
856 }
857
858 @Override
859 public List<Integer> idList(TaxonNodeFilter filter){
860 return nodeFilterDao.idList(filter);
861 }
862
863 @Override
864 public UUID monitSetSecundum(final SecundumForSubtreeConfigurator configurator) {
865 RemotingProgressMonitorThread monitorThread = new RemotingProgressMonitorThread() {
866 @Override
867 public Serializable doRun(IRemotingProgressMonitor monitor) {
868 configurator.setMonitor(monitor);
869 UpdateResult result = setSecundumForSubtree(configurator);
870 return result;
871 }
872 };
873 UUID uuid = progressMonitorService.registerNewRemotingMonitor(monitorThread);
874 monitorThread.setPriority(3);
875 monitorThread.start();
876 return uuid;
877 }
878
879
880
881
882 }