Project

General

Profile

Download (17.2 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.Collections;
15
import java.util.Comparator;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.apache.log4j.Logger;
22
import org.springframework.beans.factory.annotation.Autowired;
23
import org.springframework.stereotype.Service;
24
import org.springframework.transaction.annotation.Transactional;
25

    
26
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
27
import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator;
28
import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator.ChildHandling;
29
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
30
import eu.etaxonomy.cdm.model.description.TaxonDescription;
31
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
32
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.model.taxon.Classification;
35
import eu.etaxonomy.cdm.model.taxon.ITaxonNodeComparator;
36
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
37
import eu.etaxonomy.cdm.model.taxon.Synonym;
38
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
39
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
40
import eu.etaxonomy.cdm.model.taxon.Taxon;
41
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
42
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
43
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
44
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
45

    
46
/**
47
 * @author n.hoffmann
48
 * @created Apr 9, 2010
49
 * @version 1.0
50
 */
51
@Service
52
@Transactional(readOnly = true)
53
public class TaxonNodeServiceImpl extends AnnotatableServiceBase<TaxonNode, ITaxonNodeDao> implements ITaxonNodeService{
54
    private static final Logger logger = Logger.getLogger(TaxonNodeServiceImpl.class);
55

    
56
    @Autowired
57
    private IBeanInitializer defaultBeanInitializer;
58

    
59
    private Comparator<? super TaxonNode> taxonNodeComparator;
60

    
61
    @Autowired
62
    private ITaxonService taxonService;
63

    
64
    @Autowired
65
    private IClassificationService classService;
66

    
67
    @Autowired
68
    public void setTaxonNodeComparator(ITaxonNodeComparator<? super TaxonNode> taxonNodeComparator){
69
        this.taxonNodeComparator = (Comparator<? super TaxonNode>) taxonNodeComparator;
70
    }
71

    
72
    @Override
73
    public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
74
            List<String> propertyPaths, boolean recursive, boolean sorted) {
75
        taxonNode = dao.load(taxonNode.getUuid());
76
        List<TaxonNode> childNodes;
77
        if (recursive == true){
78
        	childNodes  = dao.listChildrenOf(taxonNode, null, null, null, recursive);
79
        }else{
80
        	childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
81
        }
82
        if (sorted){
83
        	Collections.sort(childNodes, taxonNodeComparator);
84
        }
85
        defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
86
        return childNodes;
87
    }
88

    
89
    /* (non-Javadoc)
90
     * @see eu.etaxonomy.cdm.api.service.ServiceBase#setDao(eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao)
91
     */
92
    @Override
93
    @Autowired
94
    protected void setDao(ITaxonNodeDao dao) {
95
        this.dao = dao;
96
    }
97

    
98
    /* (non-Javadoc)
99
     * @see eu.etaxonomy.cdm.api.service.ITaxonService#makeTaxonSynonym(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.Taxon)
100
     */
101
    @Override
102
    @Transactional(readOnly = false)
103
    public Synonym makeTaxonNodeASynonymOfAnotherTaxonNode(TaxonNode oldTaxonNode, TaxonNode newAcceptedTaxonNode, SynonymRelationshipType synonymRelationshipType, Reference citation, String citationMicroReference)  {
104

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

    
111
        if(oldTaxonNode.equals(newAcceptedTaxonNode)){
112
            throw new IllegalArgumentException("Taxon can not be made synonym of its own.");
113
        }
114

    
115

    
116

    
117
        Taxon oldTaxon = (Taxon) HibernateProxyHelper.deproxy(oldTaxonNode.getTaxon());
118
        Taxon newAcceptedTaxon = (Taxon) HibernateProxyHelper.deproxy(newAcceptedTaxonNode.getTaxon());
119

    
120
        // Move oldTaxon to newTaxon
121
        //TaxonNameBase<?,?> synonymName = oldTaxon.getName();
122
        TaxonNameBase<?,?> synonymName = (TaxonNameBase)HibernateProxyHelper.deproxy(oldTaxon.getName());
123
        HomotypicalGroup group = synonymName.getHomotypicalGroup();
124
        if (synonymRelationshipType == null){
125
            if (synonymName.isHomotypic(newAcceptedTaxon.getName())){
126
                synonymRelationshipType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
127
            }else{
128
                synonymRelationshipType = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
129
            }
130
        }
131

    
132
        //set homotypic group
133
        HomotypicalGroup newAcceptedTaxonHomotypicalgroup = newAcceptedTaxon.getHomotypicGroup();
134
       HibernateProxyHelper.deproxy(newAcceptedTaxonHomotypicalgroup);
135
       HibernateProxyHelper.deproxy(newAcceptedTaxon.getName());
136
        // Move Synonym Relations to new Taxon
137
        SynonymRelationship synonmyRelationship = newAcceptedTaxon.addSynonymName(synonymName,
138
                synonymRelationshipType, citation, citationMicroReference);
139
         HomotypicalGroup homotypicalGroupAcceptedTaxon = synonmyRelationship.getSynonym().getHomotypicGroup();
140
        // Move Synonym Relations to new Taxon
141
        // From ticket 3163 we can move taxon with accepted name having homotypic synonyms
142
        List<Synonym> synonymsInHomotypicalGroup = null;
143

    
144
        //the synonyms of the homotypical group of the old taxon
145
        if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
146
        	synonymsInHomotypicalGroup = oldTaxon.getSynonymsInGroup(group);
147
        }
148

    
149
        for(SynonymRelationship synRelation : oldTaxon.getSynonymRelations()){
150
            SynonymRelationshipType srt;
151
            if(synRelation.getSynonym().getName().getHomotypicalGroup()!= null
152
                    && synRelation.getSynonym().getName().getHomotypicalGroup().equals(newAcceptedTaxon.getName().getHomotypicalGroup())) {
153
                srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
154
            } else if(synRelation.getType() != null && synRelation.getType().equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())) {
155
            	if (synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){
156
            		srt = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
157
            	} else{
158
            		srt = SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF();
159
            	}
160
            } else {
161
                srt = synRelation.getType();
162

    
163
            }
164

    
165
            newAcceptedTaxon.addSynonym(synRelation.getSynonym(),
166
                    srt,
167
                    synRelation.getCitation(),
168
                    synRelation.getCitationMicroReference());
169

    
170
            /*if (synonymsInHomotypicalGroup.contains(synRelation.getSynonym()) && srt.equals(SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF())){
171
            	homotypicalGroupAcceptedTaxon.addTypifiedName(synRelation.getSynonym().getName());
172
            }*/
173

    
174
        }
175

    
176

    
177

    
178

    
179

    
180
        // CHILD NODES
181
        if(oldTaxonNode.getChildNodes() != null && oldTaxonNode.getChildNodes().size() != 0){
182
            for(TaxonNode childNode : oldTaxonNode.getChildNodes()){
183
                newAcceptedTaxonNode.addChildNode(childNode, childNode.getReference(), childNode.getMicroReference()); // childNode.getSynonymToBeUsed()
184
            }
185
        }
186

    
187
        //Move Taxon RelationShips to new Taxon
188
        Set<TaxonRelationship> obsoleteTaxonRelationships = new HashSet<TaxonRelationship>();
189
        for(TaxonRelationship taxonRelationship : oldTaxon.getTaxonRelations()){
190
            Taxon fromTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getFromTaxon());
191
            Taxon toTaxon = (Taxon) HibernateProxyHelper.deproxy(taxonRelationship.getToTaxon());
192
            if (fromTaxon == oldTaxon){
193
                newAcceptedTaxon.addTaxonRelation(taxonRelationship.getToTaxon(), taxonRelationship.getType(),
194
                        taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
195

    
196
            }else if(toTaxon == oldTaxon){
197
               fromTaxon.addTaxonRelation(newAcceptedTaxon, taxonRelationship.getType(),
198
                        taxonRelationship.getCitation(), taxonRelationship.getCitationMicroReference());
199
               taxonService.saveOrUpdate(fromTaxon);
200

    
201
            }else{
202
                logger.warn("Taxon is not part of its own Taxonrelationship");
203
            }
204
            // Remove old relationships
205

    
206
            fromTaxon.removeTaxonRelation(taxonRelationship);
207
            toTaxon.removeTaxonRelation(taxonRelationship);
208
            taxonRelationship.setToTaxon(null);
209
            taxonRelationship.setFromTaxon(null);
210
        }
211

    
212

    
213
        //Move descriptions to new taxon
214
        List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>( oldTaxon.getDescriptions()); //to avoid concurrent modification errors (newAcceptedTaxon.addDescription() modifies also oldtaxon.descritpions())
215
        for(TaxonDescription description : descriptions){
216
            String message = "Description copied from former accepted taxon: %s (Old title: %s)";
217
            message = String.format(message, oldTaxon.getTitleCache(), description.getTitleCache());
218
            description.setTitleCache(message, true);
219
            newAcceptedTaxon.addDescription(description);
220
        }
221
        taxonService.update(newAcceptedTaxon);
222
        TaxonDeletionConfigurator conf = new TaxonDeletionConfigurator();
223
        conf.setDeleteSynonymsIfPossible(false);
224
        DeleteResult result = taxonService.isDeletable(oldTaxon, conf);
225
//        conf.setDeleteNameIfPossible(false);
226
        
227
        if (result.isOk()){
228
        	 result = taxonService.deleteTaxon(oldTaxon, conf, null);
229
        }else{
230
        	TaxonNodeDeletionConfigurator config = new TaxonNodeDeletionConfigurator();
231
        	config.setDeleteTaxon(false);
232
        	conf.setTaxonNodeConfig(config);
233
        	result = deleteTaxonNode(oldTaxonNode, conf);
234
        }
235

    
236
        //oldTaxonNode.delete();
237
        return synonmyRelationship.getSynonym();
238
    }
239

    
240
    /* (non-Javadoc)
241
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNodes(java.util.List)
242
     */
243
    @Override
244
    @Transactional(readOnly = false)
245
    public DeleteResult deleteTaxonNodes(Set<ITaxonTreeNode> nodes, TaxonDeletionConfigurator config) {
246
        if (config == null){
247
        	config = new TaxonDeletionConfigurator();
248
        }
249
        DeleteResult result = new DeleteResult();
250
        List<UUID> deletedUUIDs = new ArrayList<UUID>();
251
        Classification classification = null;
252
        for (ITaxonTreeNode treeNode:nodes){
253
        	if (treeNode != null){
254
	        	if (treeNode instanceof TaxonNode){
255
	        		TaxonNode taxonNode;
256
		            taxonNode = HibernateProxyHelper.deproxy(treeNode, TaxonNode.class);
257

    
258
		            	//check whether the node has children or the children are already deleted
259
		            if(taxonNode.hasChildNodes()){
260
	            		Set<ITaxonTreeNode> children = new HashSet<ITaxonTreeNode> ();
261
	            		List<TaxonNode> childNodesList = taxonNode.getChildNodes();
262
	        			children.addAll(childNodesList);
263
	        			int compare = config.getTaxonNodeConfig().getChildHandling().compareTo(ChildHandling.DELETE);
264
	        			boolean childHandling = (compare == 0)? true: false;
265
	            		if (childHandling){
266
	            			boolean changeDeleteTaxon = false;
267
	            			if (!config.getTaxonNodeConfig().isDeleteTaxon()){
268
	            				config.getTaxonNodeConfig().setDeleteTaxon(true);
269
	            				changeDeleteTaxon = true;
270
	            			}
271
	            			DeleteResult resultNodes = deleteTaxonNodes(children, config);
272
	            			if (!resultNodes.isOk()){
273
                                result.addExceptions(resultNodes.getExceptions());
274
                                result.setStatus(resultNodes.getStatus());
275
                            }
276
	            			if (changeDeleteTaxon){
277
	            				config.getTaxonNodeConfig().setDeleteTaxon(false);
278
	            			}
279

    
280
	            		} else {
281
	            			//move the children to the parent
282
	            			TaxonNode parent = taxonNode.getParent();
283
	            			for (TaxonNode child: childNodesList){
284
	            				parent.addChildNode(child, child.getReference(), child.getMicroReference());
285
	            			}
286

    
287
	            		}
288
	            	}
289

    
290
		            classification = taxonNode.getClassification();
291

    
292
		            if (classification.getRootNode().equals(taxonNode)){
293
		            	classification.removeRootNode();
294
		            	classification = null;
295
		            }else if (classification.getChildNodes().contains(taxonNode)){
296
	            		Taxon taxon = taxonNode.getTaxon();
297
	            		classification.deleteChildNode(taxonNode);
298

    
299
		            	//node is rootNode
300
		            	if (taxon != null){
301

    
302
		            		if (config.getTaxonNodeConfig().isDeleteTaxon()){
303
		            		    taxonService.saveOrUpdate(taxon);
304
		            		    saveOrUpdate(taxonNode);
305
				            	TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
306
				            	DeleteResult resultTaxon = taxonService.deleteTaxon(taxon, configNew, classification);
307
				            	if (!resultTaxon.isOk()){
308
	                                result.addExceptions(resultTaxon.getExceptions());
309
	                                result.setStatus(resultTaxon.getStatus());
310
	                            }
311

    
312
			            	}
313
		            	}
314
	            		classification = null;
315

    
316
		            }else {
317
		            	classification = null;
318
		            	Taxon taxon = taxonNode.getTaxon();
319
		            	//node is rootNode
320
		            	if (taxon != null){
321
		            		taxonNode.getTaxon().removeTaxonNode(taxonNode);
322
		            		if (config.getTaxonNodeConfig().isDeleteTaxon()){
323
				            	TaxonDeletionConfigurator configNew = new TaxonDeletionConfigurator();
324
				            	saveOrUpdate(taxonNode);
325
				            	taxonService.saveOrUpdate(taxon);
326
				            	DeleteResult resultTaxon = taxonService.deleteTaxon(taxon, configNew, classification);
327
                                if (!resultTaxon.isOk()){
328
                                    result.addExceptions(resultTaxon.getExceptions());
329
                                    result.setStatus(resultTaxon.getStatus());
330
                                }
331
			            	}
332
		            	}
333

    
334
		            }
335

    
336
		            UUID uuid = dao.delete(taxonNode);
337
		            logger.debug("Deleted node " +uuid.toString());
338
	        	}else {
339
	        		classification = (Classification) treeNode;
340

    
341
	        	}
342

    
343
	            //deletedUUIDs.add(treeNode.getUuid());
344

    
345
	        }
346
        }
347
        if (classification != null){
348
        	DeleteResult resultClassification = classService.delete(classification);
349
        	 if (!resultClassification.isOk()){
350
                 result.addExceptions(resultClassification.getExceptions());
351
                 result.setStatus(resultClassification.getStatus());
352
             }
353
        }
354
        return result;
355

    
356
    }
357
    /* (non-Javadoc)
358
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#deleteTaxonNode(java.util.List)
359
     */
360
    @Override
361
    @Transactional(readOnly = false)
362
    public DeleteResult deleteTaxonNode(TaxonNode node, TaxonDeletionConfigurator config) {
363
    	Taxon taxon = (Taxon)HibernateProxyHelper.deproxy(node.getTaxon());
364
    	if (config == null){
365
    		config = new TaxonDeletionConfigurator();
366
    	}
367
    	if (config.getTaxonNodeConfig().isDeleteTaxon()){
368
    		return taxonService.deleteTaxon(taxon, config, node.getClassification());
369
    	} else{
370
    		DeleteResult result = new DeleteResult();
371
    		boolean success = taxon.removeTaxonNode(node);
372
    		if (success){
373
    			if (!dao.delete(node).equals(null)){
374
    				return result;
375
    			} else {
376
    				result.setError();
377
    				return result;
378
    			}
379
    		}else{
380
    			result.setError();
381
    			result.addException(new Exception("The node can not be removed from the taxon."));
382
    			return result;
383
    		}
384

    
385
    	}
386

    
387
    }
388

    
389
    /* (non-Javadoc)
390
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#listAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification, int, int)
391
     */
392
    @Override
393
    public List<TaxonNode> listAllNodesForClassification(Classification classification, Integer start, Integer end) {
394
        return dao.getTaxonOfAcceptedTaxaByClassification(classification, start, end);
395
    }
396

    
397
    /* (non-Javadoc)
398
     * @see eu.etaxonomy.cdm.api.service.ITaxonNodeService#countAllNodesForClassification(eu.etaxonomy.cdm.model.taxon.Classification)
399
     */
400
    @Override
401
    public int countAllNodesForClassification(Classification classification) {
402
        return dao.countTaxonOfAcceptedTaxaByClassification(classification);
403
    }
404

    
405

    
406

    
407
}
(78-78/84)