Project

General

Profile

Download (28.6 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
        start = start == null ? 0 : start;
125
        Integer limit = PagerUtils.limitFor(pageSize);
126
        limit = limit == null ? Integer.MAX_VALUE : limit;
127
        Long totalCount = Long.valueOf(allRecords.size());
128

    
129
        if(PagerUtils.hasResultsInRange(totalCount, pageIndex, pageSize)) {
130
            TaxonNameBase<?,?> parentName = null;
131

    
132
            for(int i = start; i < Math.min(totalCount, start + limit); i++) {
133
                CdmBase record = allRecords.get(i);
134

    
135
                if (record.isInstanceOf(TaxonNode.class)){
136
                    dtos.add(new TaxonNodeDto(CdmBase.deproxy(record, TaxonNode.class)));
137
                }else if (record.isInstanceOf(Synonym.class)){
138
                    Synonym synonym = CdmBase.deproxy(record, Synonym.class);
139
                    parentName = parentName == null? parentNode.getTaxon().getName(): parentName;
140
                    boolean isHomotypic = synonym.getName().isHomotypic(parentName);
141
                    dtos.add(new TaxonNodeDto(synonym, isHomotypic));
142
                }
143
            }
144
        }
145

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

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

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

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

    
168

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

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

    
179

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

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

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

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

    
227
            }
228

    
229
            newAcceptedTaxon.addSynonym(synRelation.getSynonym(),
230
                    srt,
231
                    synRelation.getCitation(),
232
                    synRelation.getCitationMicroReference());
233

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

    
238
        }
239

    
240

    
241

    
242

    
243

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

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

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

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

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

    
280

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

    
292
        taxonService.update(newAcceptedTaxon);
293

    
294
        taxonService.update(oldTaxon);
295

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

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

    
313
        //oldTaxonNode.delete();
314
        return result;
315
    }
316

    
317

    
318

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

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

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

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

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

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

    
387
            		} else {
388
            			//move the children to the parent
389

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

    
394
            		}
395
            	}
396

    
397
	            classification = taxonNode.getClassification();
398

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

    
406
	            	//node is rootNode
407
	            	if (taxon != null){
408

    
409
	            		if (config.getTaxonNodeConfig().isDeleteTaxon()){
410
	            		    taxonService.saveOrUpdate(taxon);
411
	            		    saveOrUpdate(taxonNode);
412

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

    
420
		            	}
421
	            	}
422
            		classification = null;
423

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

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

    
443
	            }
444

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

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

    
464
    }
465

    
466

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

    
477

    
478

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

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

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

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

    
509

    
510

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

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

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

    
560

    
561

    
562
    }
563

    
564

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

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

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

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

    
591
        TaxonNode parentParent = HibernateProxyHelper.deproxy(newParent.getParent(), TaxonNode.class);
592

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

    
610
        newParent.addChildNode(taxonNode, sortIndex, taxonNode.getReference(),  taxonNode.getMicroReference());
611

    
612
        dao.saveOrUpdate(newParent);
613

    
614
        return result;
615
    }
616

    
617

    
618

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

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

    
635

    
636
        List<TaxonNodeAgentRelation> records = null;
637

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

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

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

    
653
        UUID taxonUUID = taxonService.saveOrUpdate(newTaxon);
654
        newTaxon = (Taxon) taxonService.load(taxonUUID);
655

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

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

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

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

    
698
    }
699

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

    
717

    
718
}
(89-89/98)