minor
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TaxonNodeServiceImpl.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.api.service;
12
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.TaxonDeletionConfigurator;
29 import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;
30 import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator.ChildHandling;
31 import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
32 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
33 import eu.etaxonomy.cdm.model.description.TaxonDescription;
34 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
35 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
36 import eu.etaxonomy.cdm.model.reference.Reference;
37 import eu.etaxonomy.cdm.model.taxon.Classification;
38 import eu.etaxonomy.cdm.model.taxon.Synonym;
39 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
40 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
41 import eu.etaxonomy.cdm.model.taxon.Taxon;
42 import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
43 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
44 import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;
45 import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;
46 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
47 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
48 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
49
50 /**
51 * @author n.hoffmann
52 * @created Apr 9, 2010
53 * @version 1.0
54 */
55 @Service
56 @Transactional(readOnly = true)
57 public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{
58 private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
59
60 @Autowired
61 private IBeanInitializer defaultBeanInitializer;
62
63 private final Comparator<? super TaxonNode> taxonNodeComparator = new TaxonNodeByNameComparator();
64
65 @Autowired
66 private ITaxonService taxonService;
67
68 @Autowired
69 private IClassificationService classService;
70
71
72
73 @Override
74 public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
75 List<String> propertyPaths, boolean recursive, NodeSortMode sortMode) {
76 taxonNode = dao.load(taxonNode.getUuid());
77 List<TaxonNode> childNodes;
78 if (recursive == true){
79 childNodes = dao.listChildrenOf(taxonNode, null, null, null, recursive);
80 }else{
81 childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
82 }
83 if (sortMode != null){
84 Comparator<TaxonNode> comparator = null;
85 if (sortMode.equals(NodeSortMode.NaturalOrder)){
86 comparator = new TaxonNaturalComparator();
87 } else if (sortMode.equals(NodeSortMode.AlphabeticalOrder)){
88 comparator = new TaxonNodeByNameComparator();
89 } else if (sortMode.equals(NodeSortMode.RankAndAlphabeticalOrder)){
90 comparator = new TaxonNodeByRankAndNameComparator();
91 }
92 Collections.sort(childNodes, comparator);
93 }
94 defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
95 return childNodes;
96 }
97
98 @Override
99 @Autowired
100 protected void setDao(ITaxonNodeDao dao) {
101 this.dao = dao;
102 }
103
104 @Override
105 @Transactional(readOnly = false)
106 public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, Reference citation, String citationMicroReference) {
107
108
109 // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
110 // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
111 if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){
112 throw new IllegalArgumentException("A mandatory parameter was null.");
113 }
114
115 if(oldTaxonNode.equals(newAcceptedTaxonNode)){
116 throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
117 }
118
119
120
121 Classification classification = oldTaxonNode.getClassification();
122 Taxon oldTaxon = HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon(), Taxon.class);
123 Taxon newAcceptedTaxon = HibernateProxyHelper.deproxy(this.taxonService.load(newAcceptedTaxonNode.getTaxon().getUuid()), Taxon.class);
124
125 // Move oldTaxon to newTaxon
126 //TaxonNameBase<?,?> synonymName = oldTaxon.getName();
127 TaxonNameBase<?,?> synonymName = (TaxonNameBase)HibernateProxyHelper.deproxy(oldTaxon.getName());
128 HomotypicalGroup group = synonymName.getHomotypicalGroup();
129 group = HibernateProxyHelper.deproxy(group, HomotypicalGroup.class);
130 if (synonymRelationshipType == null){
131 if (synonymName.isHomotypic(newAcceptedTaxon.getName())){
132 synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
133 }else{
134 synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
135 }
136 }
137
138 //set homotypic group
139 HomotypicalGroup newAcceptedTaxonHomotypicalgroup = newAcceptedTaxon.getHomotypicGroup();
140 newAcceptedTaxonHomotypicalgroup = HibernateProxyHelper.deproxy(newAcceptedTaxonHomotypicalgroup, HomotypicalGroup.class);
141 TaxonNameBase newAcceptedTaxonName = HibernateProxyHelper.deproxy(newAcceptedTaxon.getName(), TaxonNameBase.class);
142 // Move Synonym Relations to new Taxon
143 SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName,
144 synonymRelationshipType, citation, citationMicroReference);
145 HomotypicalGroup homotypicalGroupAcceptedTaxon = synonmyRelationship.getSynonym().getHomotypicGroup();
146 // Move Synonym Relations to new Taxon
147 // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
148 List<Synonym> synonymsInHomotypicalGroup = null;
149
150 //the synonyms of the homotypical group of the old taxon
151 if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
152 synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
153 }
154
155 for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){
156 SynonymRelationshipType srt;
157 if(synRelation.getSynonym().getName().getHomotypicalGroup()!= null
158 && synRelation.getSynonym().getName().getHomotypicalGroup().equals(newAcceptedTaxonName.getHomotypicalGroup())) {
159 srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
160 } else if(synRelation.getType() != null && synRelation.getType().equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())) {
161 if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
162 srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
163 } else{
164 srt = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
165 }
166 } else {
167 srt = synRelation.getType();
168
169 }
170
171 newAcceptedTaxon.addSynonym(synRelation.getSynonym(),
172 srt,
173 synRelation.getCitation(),
174 synRelation.getCitationMicroReference());
175
176 /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
177 homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
178 }*/
179
180 }
181
182
183
184
185
186 // CHILD NODES
187 if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
188 List<TaxonNode> childNodes = new ArrayList<TaxonNode>();
189 for (TaxonNode childNode : oldTaxonNode.getChildNodes()){
190 childNodes.add(childNode);
191 }
192 for(TaxonNode childNode :childNodes){
193 newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
194 }
195 }
196
197 //Move Taxon RelationShips to new Taxon
198 Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();
199 for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
200 Taxon fromTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
201 Taxon toTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
202 if (fromTaxon == oldTaxon){
203 newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),
204 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
205
206 }else if(toTaxon == oldTaxon){
207 fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
208 taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
209 taxonService.saveOrUpdate(fromTaxon);
210
211 }else{
212 logger.warn("Taxon is not part of its own Taxonrelationship");
213 }
214 // Remove old relationships
215
216 fromTaxon.removeTaxonRelation(taxonRelationship);
217 toTaxon.removeTaxonRelation(taxonRelationship);
218 taxonRelationship.setToTaxon(null);
219 taxonRelationship.setFromTaxon(null);
220 }
221
222
223 //Move descriptions to new taxon
224 List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
225 for(TaxonDescription description : descriptions){
226 String message = "Description copied from former accepted taxon: %s (Old title: %s)";
227 message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());
228 description.setTitleCache(message, true);
229 //oldTaxon.removeDescription(description, false);
230 newAcceptedTaxon.addDescription(description);
231 }
232 oldTaxon.clearDescriptions();
233
234 taxonService.update(newAcceptedTaxon);
235
236 taxonService.update(oldTaxon);
237
238 TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
239 conf.setDeleteSynonymsIfPossible(false);
240 conf.setDeleteNameIfPossible(false);
241 DeleteResult result = taxonService.isDeletable(oldTaxon, conf);
242 conf.setDeleteNameIfPossible(false);
243
244 if (result.isOk()){
245 result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());
246 }else{
247 result.setStatus(Status.OK);
248 TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
249 config.setDeleteTaxon(false);
250 conf.setTaxonNodeConfig(config);
251 result.includeResult(deleteTaxonNode(oldTaxonNode, conf));
252 }
253 result.addUpdatedObject(newAcceptedTaxon);
254 //result.addUpdatedObject(oldTaxon);
255
256 //oldTaxonNode.delete();
257 return result;
258 }
259
260
261
262 /* (non-Javadoc)
263 * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#makeTaxonNodeASynonymOfAnotherTaxonNode(java.util.UUID, java.util.UUID, java.util.UUID, java.util.UUID, java.lang.String)
264 */
265 @Override
266 @Transactional(readOnly = false)
267 public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,
268 UUID newAcceptedTaxonNodeUUID,
269 SynonymRelationshipType synonymRelationshipType,
270 Reference citation,
271 String citationMicroReference) {
272
273 TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
274 TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
275 TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);
276
277 UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,
278 newTaxonNode,
279 synonymRelationshipType,
280 citation,
281 citationMicroReference);
282 result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
283 result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
284 result.setCdmEntity(oldTaxonParentNode);
285 return result;
286 }
287
288 /* (non-Javadoc)
289 * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNodes(java.util.List)
290 */
291 @Override
292 @Transactional(readOnly = false)
293 public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {
294
295 if (config == null){
296 config = new TaxonDeletionConfigurator();
297 }
298 DeleteResult result = new DeleteResult();
299 List<UUID> deletedUUIDs = new ArrayList<UUID>();
300 Classification classification = null;
301 List<TaxonNode> taxonNodes = new ArrayList<TaxonNode>(list);
302 for (TaxonNode treeNode:taxonNodes){
303 if (treeNode != null){
304
305 TaxonNode taxonNode;
306 taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);
307 TaxonNode parent = taxonNode.getParent();
308 //check whether the node has children or the children are already deleted
309 if(taxonNode.hasChildNodes()) {
310 List<TaxonNode> children = new ArrayList<TaxonNode> ();
311 List<TaxonNode> childNodesList = taxonNode.getChildNodes();
312 children.addAll(childNodesList);
313 int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);
314 boolean childHandling = (compare == 0)? true: false;
315 if (childHandling){
316 boolean changeDeleteTaxon = false;
317 if (!config.getTaxonNodeConfig().isDeleteTaxon()){
318 config.getTaxonNodeConfig().setDeleteTaxon(true);
319 changeDeleteTaxon = true;
320 }
321 DeleteResult resultNodes = deleteTaxonNodes(children, config);
322 if (!resultNodes.isOk()){
323 result.addExceptions(resultNodes.getExceptions());
324 result.setStatus(resultNodes.getStatus());
325 }
326 if (changeDeleteTaxon){
327 config.getTaxonNodeConfig().setDeleteTaxon(false);
328 }
329
330 } else {
331 //move the children to the parent
332
333 for (TaxonNode child: childNodesList){
334 parent.addChildNode(child, child.getReference(), child.getMicroReference());
335 }
336
337 }
338 }
339
340 classification = taxonNode.getClassification();
341
342 if (classification.getRootNode().equals(taxonNode)){
343 classification.removeRootNode();
344 classification = null;
345 }else if (classification.getChildNodes().contains(taxonNode)){
346 Taxon taxon = taxonNode.getTaxon();
347 classification.deleteChildNode(taxonNode);
348
349 //node is rootNode
350 if (taxon != null){
351
352 if (config.getTaxonNodeConfig().isDeleteTaxon()){
353 taxonService.saveOrUpdate(taxon);
354 saveOrUpdate(taxonNode);
355
356 TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
357 DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
358 if (!resultTaxon.isOk()){
359 result.addExceptions(resultTaxon.getExceptions());
360 result.setStatus(resultTaxon.getStatus());
361 }
362
363 }
364 }
365 classification = null;
366
367 } else {
368 classification = null;
369 Taxon taxon = taxonNode.getTaxon();
370 taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
371 if (taxon != null){
372 taxon.removeTaxonNode(taxonNode);
373 if (config.getTaxonNodeConfig().isDeleteTaxon()){
374 TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
375 saveOrUpdate(taxonNode);
376 taxonService.saveOrUpdate(taxon);
377 DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, null);
378
379 if (!resultTaxon.isOk()){
380 result.addExceptions(resultTaxon.getExceptions());
381 result.setStatus(resultTaxon.getStatus());
382 }
383 }
384 }
385
386 }
387
388 result.addUpdatedObject(parent);
389 if(result.getCdmEntity() == null){
390 result.setCdmEntity(taxonNode);
391 }
392 UUID uuid = dao.delete(taxonNode);
393 logger.debug("Deleted node " +uuid.toString());
394
395 }
396 }
397 /*if (classification != null){
398 result.addUpdatedObject(classification);
399 DeleteResult resultClassification = classService.delete(classification);
400 if (!resultClassification.isOk()){
401 result.addExceptions(resultClassification.getExceptions());
402 result.setStatus(resultClassification.getStatus());
403 }
404 }*/
405 return result;
406
407 }
408
409
410 @Override
411 @Transactional(readOnly = false)
412 public DeleteResult deleteTaxonNodes(Collection<UUID> nodeUuids, TaxonDeletionConfigurator config) {
413 List<TaxonNode> nodes = new ArrayList<TaxonNode>();
414 for(UUID nodeUuid : nodeUuids) {
415 nodes.add(dao.load(nodeUuid));
416 }
417 return deleteTaxonNodes(nodes, config);
418 }
419
420
421
422 @Override
423 @Transactional(readOnly = false)
424 public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
425 TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);
426 return deleteTaxonNode(node, config);
427 }
428
429 @Override
430 @Transactional(readOnly = false)
431 public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
432
433 Taxon taxon = (Taxon)HibernateProxyHelper.deproxy(node.getTaxon());
434 TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);
435 if (config == null){
436 config = new TaxonDeletionConfigurator();
437 }
438 DeleteResult result = new DeleteResult();
439
440 if (config.getTaxonNodeConfig().getChildHandling().equals(TaxonNodeDeletionConfigurator.ChildHandling.MOVE_TO_PARENT)){
441 Object[] children = node.getChildNodes().toArray();
442 TaxonNode childNode;
443 for (Object child: children){
444 childNode = (TaxonNode) child;
445 parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());
446 }
447 }else{
448 deleteTaxonNodes(node.getChildNodes(), config);
449 }
450
451 if (config.getTaxonNodeConfig().isDeleteTaxon() && (config.isDeleteInAllClassifications() || taxon.getTaxonNodes().size() == 1)){
452 result = taxonService.deleteTaxon(taxon.getUuid(), config, node.getClassification().getUuid());
453 result.addUpdatedObject(parent);
454 if (result.isOk()){
455 return result;
456 }
457 } else {
458 result.addUpdatedObject(taxon);
459 }
460
461 result.setCdmEntity(node);
462
463 boolean success = true;
464 if(taxon != null){
465 success = taxon.removeTaxonNode(node);
466 }
467
468 taxonService.saveOrUpdate(taxon);
469 result.addUpdatedObject(parent);
470
471 if (success){
472 result.setStatus(Status.OK);
473 parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);
474 int index = parent.getChildNodes().indexOf(node);
475 if (index > -1){
476 parent.removeChild(index);
477 }
478 if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(TaxonNodeDeletionConfigurator.ChildHandling.DELETE)).equals(null)){
479 return result;
480 } else {
481 result.setError();
482 return result;
483 }
484 }else{
485 if (dao.findByUuid(node.getUuid()) != null){
486 result.setError();
487 result.addException(new Exception("The node can not be removed from the taxon."));
488 }
489 return result;
490 }
491
492
493
494 }
495
496
497 /* (non-Javadoc)
498 * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#listAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification, int, int)
499 */
500 @Override
501 public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
502 return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
503 }
504
505 @Override
506 public int countAllNodesForClassification(Classification classification) {
507 return dao.countTaxonOfAcceptedTaxaByClassification(classification);
508 }
509
510 @Override
511 @Transactional
512 public UpdateResult moveTaxonNode(UUID taxonNodeUuid, UUID targetNodeUuid, boolean isParent){
513 TaxonNode taxonNode = dao.load(taxonNodeUuid);
514 TaxonNode targetNode = dao.load(targetNodeUuid);
515 return moveTaxonNode(taxonNode, targetNode, isParent);
516 }
517
518 @Override
519 @Transactional
520 public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, boolean isParent){
521 UpdateResult result = new UpdateResult();
522
523 Integer sortIndex;
524 if (isParent){
525
526 sortIndex = newParent.getChildNodes().size();
527 }else{
528 sortIndex = newParent.getSortIndex() +1;
529 newParent = newParent.getParent();
530 }
531 result.addUpdatedObject(newParent);
532 result.addUpdatedObject(taxonNode.getParent());
533 result.setCdmEntity(taxonNode);
534 newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(), taxonNode.getMicroReference());
535 dao.saveOrUpdate(newParent);
536
537 return result;
538 }
539
540
541
542 @Override
543 @Transactional
544 public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, boolean isParent){
545 UpdateResult result = new UpdateResult();
546 TaxonNode targetNode = dao.load(newParentNodeUuid);
547 for (UUID taxonNodeUuid: taxonNodeUuids){
548 TaxonNode taxonNode = dao.load(taxonNodeUuid);
549 result.includeResult(moveTaxonNode(taxonNode,targetNode, isParent));
550 }
551 return result;
552 }
553
554 }