Project

General

Profile

Download (28.5 KB) Statistics
| Branch: | Tag: | Revision:
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.NodeDeletionConfigurator.ChildHandling;
29
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
30
import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;
31
import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
32
import eu.etaxonomy.cdm.api.service.pager.Pager;
33
import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
34
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
35
import eu.etaxonomy.cdm.hibernate.HHH_9751_Util;
36
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
37
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
38
import eu.etaxonomy.cdm.model.common.CdmBase;
39
import eu.etaxonomy.cdm.model.common.DefinedTerm;
40
import eu.etaxonomy.cdm.model.description.TaxonDescription;
41
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
42
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43
import eu.etaxonomy.cdm.model.reference.Reference;
44
import eu.etaxonomy.cdm.model.taxon.Classification;
45
import eu.etaxonomy.cdm.model.taxon.HomotypicGroupTaxonComparator;
46
import eu.etaxonomy.cdm.model.taxon.Synonym;
47
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
48
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
49
import eu.etaxonomy.cdm.model.taxon.Taxon;
50
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
51
import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
52
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
53
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
54
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
55
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
56

    
57
/**
58
 * @author n.hoffmann
59
 * @created Apr 9, 2010
60
 * @version 1.0
61
 */
62
@Service
63
@Transactional(readOnly = true)
64
public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{
65
    private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
66

    
67
    @Autowired
68
    private IBeanInitializer defaultBeanInitializer;
69

    
70
    @Autowired
71
    private ITaxonService taxonService;
72

    
73
    @Autowired
74
    private IAgentService agentService;
75

    
76
    @Override
77
    public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
78
            List<String> propertyPaths, boolean recursive, NodeSortMode sortMode) {
79

    
80
        getSession().refresh(taxonNode);
81
        List<TaxonNode> childNodes;
82
        if (recursive == true){
83
        	childNodes  = dao.listChildrenOf(taxonNode, null, null, null, recursive);
84
        }else{
85
        	childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
86
        }
87

    
88
        HHH_9751_Util.removeAllNull(childNodes);
89

    
90
        if (sortMode != null){
91
            Comparator<TaxonNode> comparator = sortMode.newComparator();
92
        	Collections.sort(childNodes, comparator);
93
        }
94
        defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
95
        return childNodes;
96
    }
97

    
98
    /**
99
     * {@inheritDoc}
100
     */
101
    @Override
102
    public Pager<TaxonNodeDto> pageChildNodesDTOs(UUID taxonNodeUuid, boolean recursive,
103
            boolean doSynonyms, NodeSortMode sortMode,
104
            Integer pageSize, Integer pageIndex) {
105

    
106
        TaxonNode parentNode = dao.load(taxonNodeUuid);
107

    
108
        List<CdmBase> allRecords = new ArrayList<>();
109

    
110
        //acceptedTaxa
111
        List<TaxonNode> childNodes = loadChildNodesOfTaxonNode(parentNode, null, recursive, sortMode);
112
        allRecords.addAll(childNodes);
113

    
114
        //add synonyms if pager is not yet full synonyms
115
        List<Synonym> synList = new ArrayList<>(parentNode.getTaxon().getSynonyms());
116
        Collections.sort(synList, new HomotypicGroupTaxonComparator(null));
117
        //TODO: test sorting
118

    
119
        allRecords.addAll(synList);
120

    
121

    
122
        List<TaxonNodeDto> dtos = new ArrayList<>(pageSize==null?25:pageSize);
123
        Integer start = PagerUtils.startFor(pageSize, pageIndex);
124
        Integer limit = PagerUtils.limitFor(pageSize);
125
        limit = limit == null ? Integer.MAX_VALUE : limit;
126
        Long totalCount = Long.valueOf(allRecords.size());
127

    
128
            TaxonNameBase<?,?> parentName = null;
129

    
130
//            for(int i = start; i < Math.min(totalCount, start + limit); i++) {
131
            for(CdmBase record : PagerUtils.pageList(allRecords, pageIndex, pageSize)) {
132
                if (record.isInstanceOf(TaxonNode.class)){
133
                    dtos.add(new TaxonNodeDto(CdmBase.deproxy(record, TaxonNode.class)));
134
                }else if (record.isInstanceOf(Synonym.class)){
135
                    Synonym synonym = CdmBase.deproxy(record, Synonym.class);
136
                    parentName = parentName == null? parentNode.getTaxon().getName(): parentName;
137
                    boolean isHomotypic = synonym.getName().isHomotypic(parentName);
138
                    dtos.add(new TaxonNodeDto(synonym, isHomotypic));
139
                }
140
            }
141

    
142
//        }
143

    
144
        return new DefaultPagerImpl<TaxonNodeDto>(pageIndex, totalCount, pageSize , dtos);
145
    }
146

    
147
    @Override
148
    public TaxonNodeDto parentDto(UUID taxonNodeUuid) {
149
        TaxonNode taxonNode = dao.load(taxonNodeUuid);
150
        if(taxonNode.getParent() != null) {
151
            return new TaxonNodeDto(taxonNode.getParent());
152
        }
153
        return null;
154
    }
155

    
156
    @Override
157
    @Autowired
158
    protected void setDao(ITaxonNodeDao dao) {
159
        this.dao = dao;
160
    }
161

    
162
    @Override
163
    @Transactional(readOnly = false)
164
    public DeleteResult makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, Reference citation, String citationMicroReference)  {
165

    
166

    
167
        // TODO at the moment this method only moves synonym-, concept relations and descriptions to the new accepted taxon
168
        // in a future version we also want to move cdm data like annotations, marker, so., but we will need a policy for that
169
        if (oldTaxonNode == null || newAcceptedTaxonNode == null || oldTaxonNode.getTaxon().getName() == null){
170
            throw new IllegalArgumentException("A mandatory parameter was null.");
171
        }
172

    
173
        if(oldTaxonNode.equals(newAcceptedTaxonNode)){
174
            throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
175
        }
176

    
177

    
178
        Classification classification = oldTaxonNode.getClassification();
179
        Taxon oldTaxon = HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
180
        Taxon newAcceptedTaxon = (Taxon)this.taxonService.load(newAcceptedTaxonNode.getTaxon().getUuid());
181
        // Move oldTaxon to newTaxon
182
        //TaxonNameBase<?,?> synonymName = oldTaxon.getName();
183
        TaxonNameBase<?,?> synonymName = HibernateProxyHelper.deproxy(oldTaxon.getName());
184
        HomotypicalGroup group = synonymName.getHomotypicalGroup();
185
        group = HibernateProxyHelper.deproxy(group, HomotypicalGroup.class);
186
        if (synonymRelationshipType == null){
187
            if (synonymName.isHomotypic(newAcceptedTaxon.getName())){
188
                synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
189
            }else{
190
                synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
191
            }
192
        }
193

    
194
        //set homotypic group
195
        HomotypicalGroup newAcceptedTaxonHomotypicalgroup = newAcceptedTaxon.getHomotypicGroup();
196
        newAcceptedTaxonHomotypicalgroup = HibernateProxyHelper.deproxy(newAcceptedTaxonHomotypicalgroup, HomotypicalGroup.class);
197
        TaxonNameBase newAcceptedTaxonName = HibernateProxyHelper.deproxy(newAcceptedTaxon.getName(), TaxonNameBase.class);
198
        // Move Synonym Relations to new Taxon
199
        SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName,
200
                synonymRelationshipType, citation, citationMicroReference);
201
         HomotypicalGroup homotypicalGroupAcceptedTaxon = synonmyRelationship.getSynonym().getHomotypicGroup();
202
        // Move Synonym Relations to new Taxon
203
        // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
204
        List<Synonym> synonymsInHomotypicalGroup = null;
205

    
206
        //the synonyms of the homotypical group of the old taxon
207
        if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
208
        	synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
209
        }
210

    
211
        for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){
212
            SynonymRelationshipType srt;
213
            if(synRelation.getSynonym().getName().getHomotypicalGroup()!= null
214
                    && synRelation.getSynonym().getName().getHomotypicalGroup().equals(newAcceptedTaxonName.getHomotypicalGroup())) {
215
                srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
216
            } else if(synRelation.getType() != null && synRelation.getType().equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())) {
217
            	if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
218
            		srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
219
            	} else{
220
            		srt = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
221
            	}
222
            } else {
223
                srt = synRelation.getType();
224

    
225
            }
226

    
227
            newAcceptedTaxon.addSynonym(synRelation.getSynonym(),
228
                    srt,
229
                    synRelation.getCitation(),
230
                    synRelation.getCitationMicroReference());
231

    
232
            /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
233
            	homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
234
            }*/
235

    
236
        }
237

    
238

    
239

    
240

    
241

    
242
        // CHILD NODES
243
        if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
244
        	List<TaxonNode> childNodes = new ArrayList<TaxonNode>();
245
        	for (TaxonNode childNode : oldTaxonNode.getChildNodes()){
246
        		childNodes.add(childNode);
247
        	}
248
            for(TaxonNode childNode :childNodes){
249
                newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
250
            }
251
        }
252

    
253
        //Move Taxon RelationShips to new Taxon
254
        Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();
255
        for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
256
            Taxon fromTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
257
            Taxon toTaxon = HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
258
            if (fromTaxon == oldTaxon){
259
                newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),
260
                        taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
261

    
262
            }else if(toTaxon == oldTaxon){
263
               fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
264
                        taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
265
               taxonService.saveOrUpdate(fromTaxon);
266

    
267
            }else{
268
                logger.warn("Taxon is not part of its own Taxonrelationship");
269
            }
270
            // Remove old relationships
271

    
272
            fromTaxon.removeTaxonRelation(taxonRelationship);
273
            toTaxon.removeTaxonRelation(taxonRelationship);
274
            taxonRelationship.setToTaxon(null);
275
            taxonRelationship.setFromTaxon(null);
276
        }
277

    
278

    
279
        //Move descriptions to new taxon
280
        List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
281
        for(TaxonDescription description : descriptions){
282
            String message = "Description copied from former accepted taxon: %s (Old title: %s)";
283
            message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());
284
            description.setTitleCache(message, true);
285
            //oldTaxon.removeDescription(description, false);
286
            newAcceptedTaxon.addDescription(description);
287
        }
288
        oldTaxon.clearDescriptions();
289

    
290
        taxonService.update(newAcceptedTaxon);
291

    
292
        taxonService.update(oldTaxon);
293

    
294
        TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
295
        conf.setDeleteSynonymsIfPossible(false);
296
        DeleteResult result = taxonService.isDeletable(oldTaxon, conf);
297
        conf.setDeleteNameIfPossible(false);
298

    
299
        if (result.isOk()){
300
        	 result = taxonService.deleteTaxon(oldTaxon.getUuid(), conf, classification.getUuid());
301
        }else{
302
        	result.setStatus(Status.OK);
303
        	TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
304
        	config.setDeleteElement(false);
305
        	conf.setTaxonNodeConfig(config);
306
        	result.includeResult(deleteTaxonNode(oldTaxonNode, conf));
307
        }
308
        result.addUpdatedObject(newAcceptedTaxon);
309
        result.addUpdatedObject(oldTaxon);
310

    
311
        //oldTaxonNode.delete();
312
        return result;
313
    }
314

    
315

    
316

    
317
    /* (non-Javadoc)
318
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#makeTaxonNodeASynonymOfAnotherTaxonNode(java.util.UUID, java.util.UUID, java.util.UUID, java.util.UUID, java.lang.String)
319
     */
320
    @Override
321
    @Transactional(readOnly = false)
322
    public UpdateResult makeTaxonNodeASynonymOfAnotherTaxonNode(UUID oldTaxonNodeUuid,
323
            UUID newAcceptedTaxonNodeUUID,
324
            SynonymRelationshipType synonymRelationshipType,
325
            Reference citation,
326
            String citationMicroReference) {
327

    
328
        TaxonNode oldTaxonNode = dao.load(oldTaxonNodeUuid);
329
        TaxonNode oldTaxonParentNode = oldTaxonNode.getParent();
330
        TaxonNode newTaxonNode = dao.load(newAcceptedTaxonNodeUUID);
331

    
332
        UpdateResult result = makeTaxonNodeASynonymOfAnotherTaxonNode(oldTaxonNode,
333
                newTaxonNode,
334
                synonymRelationshipType,
335
                citation,
336
                citationMicroReference);
337
        result.addUpdatedCdmId(new CdmEntityIdentifier(oldTaxonParentNode.getId(), TaxonNode.class));
338
        result.addUpdatedCdmId(new CdmEntityIdentifier(newTaxonNode.getId(), TaxonNode.class));
339
        result.setCdmEntity(oldTaxonParentNode);
340
        return result;
341
    }
342

    
343
    /* (non-Javadoc)
344
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNodes(java.util.List)
345
     */
346
    @Override
347
    @Transactional(readOnly = false)
348
    public DeleteResult deleteTaxonNodes(List<TaxonNode> list, TaxonDeletionConfigurator config) {
349

    
350
        if (config == null){
351
        	config = new TaxonDeletionConfigurator();
352
        }
353
        DeleteResult result = new DeleteResult();
354
        List<UUID> deletedUUIDs = new ArrayList<UUID>();
355
        Classification classification = null;
356
        List<TaxonNode> taxonNodes = new ArrayList<TaxonNode>(list);
357
        for (TaxonNode treeNode:taxonNodes){
358
        	if (treeNode != null){
359

    
360
        		TaxonNode taxonNode;
361
	            taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);
362
	            TaxonNode parent = taxonNode.getParent();
363
	            	//check whether the node has children or the children are already deleted
364
	            if(taxonNode.hasChildNodes()) {
365
            		List<TaxonNode> children = new ArrayList<TaxonNode> ();
366
            		List<TaxonNode> childNodesList = taxonNode.getChildNodes();
367
        			children.addAll(childNodesList);
368
        			int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);
369
        			boolean childHandling = (compare == 0)? true: false;
370
            		if (childHandling){
371
            			boolean changeDeleteTaxon = false;
372
            			if (!config.getTaxonNodeConfig().isDeleteTaxon()){
373
            				config.getTaxonNodeConfig().setDeleteTaxon(true);
374
            				changeDeleteTaxon = true;
375
            			}
376
            			DeleteResult resultNodes = deleteTaxonNodes(children, config);
377
            			if (!resultNodes.isOk()){
378
                            result.addExceptions(resultNodes.getExceptions());
379
                            result.setStatus(resultNodes.getStatus());
380
                        }
381
            			if (changeDeleteTaxon){
382
            				config.getTaxonNodeConfig().setDeleteTaxon(false);
383
            			}
384

    
385
            		} else {
386
            			//move the children to the parent
387

    
388
            			for (TaxonNode child: childNodesList){
389
            				parent.addChildNode(child, child.getReference(), child.getMicroReference());
390
            			}
391

    
392
            		}
393
            	}
394

    
395
	            classification = taxonNode.getClassification();
396

    
397
	            if (classification.getRootNode().equals(taxonNode)){
398
	            	classification.removeRootNode();
399
	            	classification = null;
400
	            }else if (classification.getChildNodes().contains(taxonNode)){
401
            		Taxon taxon = taxonNode.getTaxon();
402
            		classification.deleteChildNode(taxonNode);
403

    
404
	            	//node is rootNode
405
	            	if (taxon != null){
406

    
407
	            		if (config.getTaxonNodeConfig().isDeleteTaxon()){
408
	            		    taxonService.saveOrUpdate(taxon);
409
	            		    saveOrUpdate(taxonNode);
410

    
411
			            	TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
412
			            	DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, classification.getUuid());
413
			            	if (!resultTaxon.isOk()){
414
                                result.addExceptions(resultTaxon.getExceptions());
415
                                result.setStatus(resultTaxon.getStatus());
416
                            }
417

    
418
		            	}
419
	            	}
420
            		classification = null;
421

    
422
	            } else {
423
	            	classification = null;
424
	            	Taxon taxon = taxonNode.getTaxon();
425
	            	taxon = HibernateProxyHelper.deproxy(taxon, Taxon.class);
426
	            	if (taxon != null){
427
	            		taxon.removeTaxonNode(taxonNode);
428
	            		if (config.getTaxonNodeConfig().isDeleteTaxon()){
429
			            	TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
430
			            	saveOrUpdate(taxonNode);
431
			            	taxonService.saveOrUpdate(taxon);
432
			            	DeleteResult resultTaxon = taxonService.deleteTaxon(taxon.getUuid(), configNew, null);
433

    
434
                            if (!resultTaxon.isOk()){
435
                                result.addExceptions(resultTaxon.getExceptions());
436
                                result.setStatus(resultTaxon.getStatus());
437
                            }
438
		            	}
439
	            	}
440

    
441
	            }
442

    
443
	            result.addUpdatedObject(parent);
444
	            if(result.getCdmEntity() == null){
445
	                result.setCdmEntity(taxonNode);
446
                }
447
	            UUID uuid = dao.delete(taxonNode);
448
	            logger.debug("Deleted node " +uuid.toString());
449

    
450
	        }
451
        }
452
        /*if (classification != null){
453
            result.addUpdatedObject(classification);
454
        	DeleteResult resultClassification = classService.delete(classification);
455
        	 if (!resultClassification.isOk()){
456
                 result.addExceptions(resultClassification.getExceptions());
457
                 result.setStatus(resultClassification.getStatus());
458
             }
459
        }*/
460
        return result;
461

    
462
    }
463

    
464

    
465
    @Override
466
    @Transactional(readOnly = false)
467
    public DeleteResult deleteTaxonNodes(Collection<UUID> nodeUuids, TaxonDeletionConfigurator config) {
468
        List<TaxonNode> nodes = new ArrayList<TaxonNode>();
469
        for(UUID nodeUuid : nodeUuids) {
470
            nodes.add(dao.load(nodeUuid));
471
        }
472
        return deleteTaxonNodes(nodes, config);
473
    }
474

    
475

    
476

    
477
    @Override
478
    @Transactional(readOnly = false)
479
    public DeleteResult deleteTaxonNode(UUID nodeUUID, TaxonDeletionConfigurator config) {
480

    
481
    	TaxonNode node = HibernateProxyHelper.deproxy(dao.load(nodeUUID), TaxonNode.class);
482
    	return deleteTaxonNode(node, config);
483
    }
484

    
485
    @Override
486
    @Transactional(readOnly = false)
487
    public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
488
        DeleteResult result = new DeleteResult();
489
        if (node == null){
490
            result.setAbort();
491
            result.addException(new Exception("The TaxonNode was already deleted."));
492
            return result;
493
        }
494
        Taxon taxon = null;
495
        try{
496
            taxon = HibernateProxyHelper.deproxy(node.getTaxon());
497
        }catch(NullPointerException e){
498
            result.setAbort();
499
            result.addException(new Exception("The Taxon was already deleted."));
500

    
501
        }
502
    	TaxonNode parent = HibernateProxyHelper.deproxy(node.getParent(), TaxonNode.class);
503
    	if (config == null){
504
    		config = new TaxonDeletionConfigurator();
505
    	}
506

    
507

    
508

    
509
    	if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.MOVE_TO_PARENT)){
510
    	   Object[] children = node.getChildNodes().toArray();
511
    	   TaxonNode childNode;
512
    	   for (Object child: children){
513
    	       childNode = (TaxonNode) child;
514
    	       parent.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference());
515
    	   }
516
    	}else{
517
    	    deleteTaxonNodes(node.getChildNodes(), config);
518
    	}
519

    
520
    	if (taxon != null){
521
        	if (config.getTaxonNodeConfig().isDeleteTaxon() && (config.isDeleteInAllClassifications() || taxon.getTaxonNodes().size() == 1)){
522
        		result = taxonService.deleteTaxon(taxon.getUuid(), config, node.getClassification().getUuid());
523
        		result.addUpdatedObject(parent);
524
        		if (result.isOk()){
525
        			return result;
526
        		}
527
        	} else {
528
        	    result.addUpdatedObject(taxon);
529
        	}
530
    	}
531
    	result.setCdmEntity(node);
532
    	boolean success = taxon.removeTaxonNode(node);
533
    	dao.save(parent);
534
    	taxonService.saveOrUpdate(taxon);
535
    	result.addUpdatedObject(parent);
536

    
537
    	if (success){
538
			result.setStatus(Status.OK);
539
			parent = HibernateProxyHelper.deproxy(parent, TaxonNode.class);
540
			int index = parent.getChildNodes().indexOf(node);
541
			if (index > -1){
542
			    parent.removeChild(index);
543
			}
544
    		if (!dao.delete(node, config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)).equals(null)){
545
    			return result;
546
    		} else {
547
    			result.setError();
548
    			return result;
549
    		}
550
    	}else{
551
    	    if (dao.findByUuid(node.getUuid()) != null){
552
        		result.setError();
553
        		result.addException(new Exception("The node can not be removed from the taxon."));
554
    		}
555
    		return result;
556
    	}
557

    
558

    
559

    
560
    }
561

    
562

    
563
    /* (non-Javadoc)
564
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#listAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification, int, int)
565
     */
566
    @Override
567
    public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
568
        return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
569
    }
570

    
571
    @Override
572
    public int countAllNodesForClassification(Classification classification) {
573
        return dao.countTaxonOfAcceptedTaxaByClassification(classification);
574
    }
575

    
576
    @Override
577
    @Transactional
578
    public UpdateResult moveTaxonNode(UUID taxonNodeUuid, UUID targetNodeUuid, int movingType){
579
        TaxonNode taxonNode = HibernateProxyHelper.deproxy(dao.load(taxonNodeUuid), TaxonNode.class);
580
    	TaxonNode targetNode = HibernateProxyHelper.deproxy(dao.load(targetNodeUuid), TaxonNode.class);
581
    	return moveTaxonNode(taxonNode, targetNode, movingType);
582
    }
583

    
584
    @Override
585
    @Transactional
586
    public UpdateResult moveTaxonNode(TaxonNode taxonNode, TaxonNode newParent, int movingType){
587
        UpdateResult result = new UpdateResult();
588

    
589
        TaxonNode parentParent = HibernateProxyHelper.deproxy(newParent.getParent(), TaxonNode.class);
590

    
591
        Integer sortIndex = -1;
592
        if (movingType == 0){
593
            sortIndex = 0;
594
        }else if (movingType == 1){
595
            sortIndex = newParent.getSortIndex();
596
            newParent = parentParent;
597
        } else if (movingType == 2){
598
            sortIndex = newParent.getSortIndex() +1;
599
            newParent = parentParent;
600
        } else{
601
            result.setAbort();
602
            result.addException(new Exception("The moving type "+ movingType +" is not supported."));
603
        }
604
        result.addUpdatedObject(newParent);
605
        result.addUpdatedObject(taxonNode.getParent());
606
        result.setCdmEntity(taxonNode);
607

    
608
        newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(),  taxonNode.getMicroReference());
609

    
610
        dao.saveOrUpdate(newParent);
611

    
612
        return result;
613
    }
614

    
615

    
616

    
617
    @Override
618
    @Transactional
619
    public UpdateResult moveTaxonNodes(Set<UUID> taxonNodeUuids, UUID newParentNodeUuid, int movingType){
620
        UpdateResult result = new UpdateResult();
621
        TaxonNode targetNode = dao.load(newParentNodeUuid);
622
        for (UUID taxonNodeUuid: taxonNodeUuids){
623
            TaxonNode taxonNode = dao.load(taxonNodeUuid);
624
            result.includeResult(moveTaxonNode(taxonNode,targetNode, movingType));
625
        }
626
        return result;
627
    }
628

    
629
    @Override
630
    public Pager<TaxonNodeAgentRelation> pageTaxonNodeAgentRelations(UUID taxonUuid, UUID classificationUuid,
631
            UUID agentUuid, UUID rankUuid, UUID relTypeUuid, Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
632

    
633

    
634
        List<TaxonNodeAgentRelation> records = null;
635

    
636
        long count = dao.countTaxonNodeAgentRelations(taxonUuid, classificationUuid, agentUuid, rankUuid, relTypeUuid);
637
        if(PagerUtils.hasResultsInRange(count, pageIndex, pageSize)) {
638
            records = dao.listTaxonNodeAgentRelations(taxonUuid, classificationUuid,
639
                    agentUuid, rankUuid, relTypeUuid, PagerUtils.startFor(pageSize, pageIndex), PagerUtils.limitFor(pageSize), propertyPaths);
640
        }
641

    
642
        Pager<TaxonNodeAgentRelation> pager = new DefaultPagerImpl<TaxonNodeAgentRelation>(pageIndex, count, pageSize, records);
643
        return pager;
644
    }
645

    
646
    @Override
647
    @Transactional
648
    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, Taxon newTaxon, Reference ref, String microref){
649
        UpdateResult result = new UpdateResult();
650

    
651
        UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
652
        newTaxon = (Taxon) taxonService.load(taxonUUID);
653

    
654
        TaxonNode parent = dao.load(parentNodeUuid);
655
        TaxonNode child = null;
656
        try{
657
            child = parent.addChildTaxon(newTaxon, parent.getReference(), parent.getMicroReference());
658
        }catch(Exception e){
659
            result.addException(e);
660
            result.setError();
661
            return result;
662
        }
663
//        child = dao.save(child);
664

    
665
        dao.saveOrUpdate(parent);
666
        result.addUpdatedObject(parent);
667
        if (child != null){
668
            result.setCdmEntity(child);
669
        }
670
        return result;
671

    
672
    }
673
    @Override
674
    @Transactional
675
    public UpdateResult createNewTaxonNode(UUID parentNodeUuid, UUID taxonUuid, Reference ref, String microref){
676
        UpdateResult result = new UpdateResult();
677
        TaxonNode parent = dao.load(parentNodeUuid);
678
        Taxon taxon = (Taxon) taxonService.load(taxonUuid);
679
        TaxonNode child = null;
680
        try{
681
            child = parent.addChildTaxon(taxon, parent.getReference(), parent.getMicroReference());
682
        }catch(Exception e){
683
            result.addException(e);
684
            result.setError();
685
            return result;
686
        }
687
//        child = dao.save(child);
688

    
689
        dao.saveOrUpdate(parent);
690
        result.addUpdatedObject(parent);
691
        if (child != null){
692
            result.setCdmEntity(child);
693
        }
694
        return result;
695

    
696
    }
697

    
698
    @Override
699
    @Transactional
700
    public UpdateResult addTaxonNodeAgentRelation(UUID taxonNodeUUID, UUID agentUUID, DefinedTerm relationshipType){
701
        UpdateResult result = new UpdateResult();
702
        TaxonNode node = dao.load(taxonNodeUUID);
703
        TeamOrPersonBase agent = (TeamOrPersonBase) agentService.load(agentUUID);
704
        node.addAgentRelation(relationshipType, agent);
705
        try{
706
            dao.merge(node, true);
707
        }catch (Exception e){
708
            result.setError();
709
            result.addException(e);
710
        }
711
        result.setCdmEntity(node);
712
        return result;
713
    }
714

    
715

    
716
}
(89-89/98)