Project

General

Profile

Download (34.2 KB) Statistics
| Branch: | Tag: | Revision:
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
}
(93-93/101)