Project

General

Profile

« Previous | Next » 

Revision 59174ab0

Added by Andreas Müller over 3 years ago

ref #4866, ref #9228 implement subtree clone in branch

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Classification.java
350 350
        }
351 351

  
352 352
        for (TaxonNode taxonNode: taxon.getTaxonNodes()){
353
        	Classification classification = deproxy(taxonNode.getClassification(), Classification.class);
353
        	Classification classification = deproxy(taxonNode.getClassification());
354 354
            if (classification.equals(this)){
355 355
                return taxonNode;
356 356
            }
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Taxon.java
1739 1739
     * @see java.lang.Object#clone()
1740 1740
     */
1741 1741
    @Override
1742
    public Object clone() {
1742
    public Taxon clone() {
1743
        return clone(true, true, true, true);
1744
    }
1745

  
1746
    public Taxon clone(boolean withSynonyms, boolean withTaxonRelations, boolean withDescriptions, boolean withMedia) {
1743 1747
        Taxon result;
1744 1748
        result = (Taxon)super.clone();
1745 1749

  
1746 1750
        result.setRelationsFromThisTaxon(new HashSet<>());
1747 1751

  
1748
        for (TaxonRelationship fromRelationship : this.getRelationsFromThisTaxon()){
1749
            TaxonRelationship newRelationship = (TaxonRelationship)fromRelationship.clone();
1750
            newRelationship.setRelatedFrom(result);
1751
            result.relationsFromThisTaxon.add(newRelationship);
1752
        }
1752
        if (withTaxonRelations){
1753
            for (TaxonRelationship fromRelationship : this.getRelationsFromThisTaxon()){
1754
                TaxonRelationship newRelationship = (TaxonRelationship)fromRelationship.clone();
1755
                newRelationship.setRelatedFrom(result);
1756
                result.relationsFromThisTaxon.add(newRelationship);
1757
            }
1753 1758

  
1754
        result.setRelationsToThisTaxon(new HashSet<>());
1755
        for (TaxonRelationship toRelationship : this.getRelationsToThisTaxon()){
1756
            TaxonRelationship newRelationship = (TaxonRelationship)toRelationship.clone();
1757
            newRelationship.setRelatedTo(result);
1758
            result.relationsToThisTaxon.add(newRelationship);
1759
            result.setRelationsToThisTaxon(new HashSet<>());
1760
            for (TaxonRelationship toRelationship : this.getRelationsToThisTaxon()){
1761
                TaxonRelationship newRelationship = (TaxonRelationship)toRelationship.clone();
1762
                newRelationship.setRelatedTo(result);
1763
                result.relationsToThisTaxon.add(newRelationship);
1764
            }
1759 1765
        }
1760 1766

  
1761 1767
        //clone synonyms (is this wanted or should we remove synonyms
1762 1768
        result.synonyms = new HashSet<>();
1763
        for (Synonym synonym : this.getSynonyms()){
1764
            Synonym newSyn = (Synonym)synonym.clone();
1765
            newSyn.setAcceptedTaxon(result);
1769
        if(withSynonyms){
1770
            for (Synonym synonym : this.getSynonyms()){
1771
                Synonym newSyn = (Synonym)synonym.clone();
1772
                newSyn.setAcceptedTaxon(result);
1773
            }
1766 1774
        }
1767 1775

  
1768 1776
        result.descriptions = new HashSet<>();
1769 1777
        for (TaxonDescription description : this.getDescriptions()){
1770
            TaxonDescription newDescription = (TaxonDescription)description.clone();
1771
            result.addDescription(newDescription);
1778
            if (description.isImageGallery() && withMedia ||
1779
                    !description.isImageGallery() && withDescriptions){
1780
                TaxonDescription newDescription = (TaxonDescription)description.clone();
1781
                result.addDescription(newDescription);
1782
            }
1772 1783
        }
1773 1784

  
1774 1785
        result.taxonNodes = new HashSet<>();
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/ClassificationServiceImpl.java
34 34

  
35 35
import eu.etaxonomy.cdm.api.service.config.CreateHierarchyForClassificationConfigurator;
36 36
import eu.etaxonomy.cdm.api.service.config.NodeDeletionConfigurator.ChildHandling;
37
import eu.etaxonomy.cdm.api.service.config.SubtreeCloneConfigurator;
37 38
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
38 39
import eu.etaxonomy.cdm.api.service.dto.EntityDTO;
39 40
import eu.etaxonomy.cdm.api.service.dto.GroupedTaxonDTO;
......
47 48
import eu.etaxonomy.cdm.exception.FilterException;
48 49
import eu.etaxonomy.cdm.exception.UnpublishedException;
49 50
import eu.etaxonomy.cdm.hibernate.HHH_9751_Util;
50
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
51 51
import eu.etaxonomy.cdm.model.common.CdmBase;
52 52
import eu.etaxonomy.cdm.model.common.ITreeNode;
53 53
import eu.etaxonomy.cdm.model.common.MarkerType;
......
68 68
import eu.etaxonomy.cdm.model.taxon.Taxon;
69 69
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
70 70
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
71
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
71
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
72 72
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
73 73
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
74 74
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
......
104 104
    @Autowired
105 105
    private ITaxonNodeService taxonNodeService;
106 106

  
107
    @Autowired
108
    private IReferenceService referenceService;
109

  
107 110
    @Autowired
108 111
    private IDefinedTermDao termDao;
109 112

  
......
137 140

  
138 141
    @Override
139 142
    @Transactional(readOnly = false)
140
    public UpdateResult cloneClassification(UUID classificationUuid,
141
    		String name, Reference sec, TaxonRelationshipType relationshipType) {
143
    public UpdateResult cloneClassification(SubtreeCloneConfigurator config) {
142 144
        UpdateResult result = new UpdateResult();
143
    	Classification classification = load(classificationUuid);
144
    	Classification clone = Classification.NewInstance(name);
145
    	clone.setReference(sec);
145

  
146
        if (config.getSubTreeUuids().isEmpty()){
147
            return result;
148
        }
149

  
150
        //TODO error handling
151
        Reference taxonSecundum = config.isReuseTaxa() || config.isReuseTaxonSecundum() || config.getTaxonSecundumUuid() == null ?
152
                null : referenceService.find(config.getTaxonSecundumUuid());
153
        config.setTaxonSecundum(taxonSecundum);
154

  
155
        Reference parentChildReference = config.isReuseParentChildReference() || config.getParentChildReferenceUuid() == null ?
156
                null : referenceService.find(config.getParentChildReferenceUuid());
157
        config.setParentChildReference(parentChildReference);
158

  
159
        Reference taxonRelationshipReference = config.getRelationTypeToOldTaxon() == null ?
160
                null : referenceService.find(config.getRelationshipReferenceUuid());
161
        config.setRelationshipReference(taxonRelationshipReference);
162

  
163
        Classification classificationClone = Classification.NewInstance(config.getClassificationName());
164

  
165
        if (config.isReuseClassificationReference()){
166
            TaxonNode anyNode = taxonNodeDao.findByUuid(config.getSubTreeUuids().iterator().next());
167
            if (anyNode != null){
168
                Reference oldClassificationRef = anyNode.getClassification().getReference();
169
                classificationClone.setReference(oldClassificationRef);
170
            }
171
        }else if (config.getClassificationReferenceUuid() != null) {
172
            Reference classificationReference = referenceService.find(config.getClassificationReferenceUuid());
173
            classificationClone.setReference(classificationReference);
174
        }
146 175

  
147 176
    	//clone taxa and taxon nodes
148
    	List<TaxonNode> childNodes = classification.getRootNode().getChildNodes();
149
    	for (TaxonNode taxonNode : childNodes) {
150
    		addChildTaxa(taxonNode, null, clone, relationshipType);
177
//    	List<Integer> childNodeIds = taxonNodeService.idList(taxonNodeFilter);
178
//    	List<TaxonNode> childNodes = taxonNodeService.loadByIds(childNodeIds, null);
179
    	List<TaxonNode> rootNodes = taxonNodeService.find(config.getSubTreeUuids());
180
    	for (TaxonNode taxonNode : rootNodes) {
181
    	    addChildTaxaToClone(taxonNode, classificationClone.getRootNode(), config);
151 182
    	}
152
    	dao.saveOrUpdate(clone);
153
    	result.setCdmEntity(clone);
183
    	dao.saveOrUpdate(classificationClone);
184
    	result.setCdmEntity(classificationClone);
154 185
    	return result;
155 186
    }
156 187

  
157
    private void addChildTaxa(TaxonNode originalParentNode, TaxonNode cloneParentNode, Classification classification, TaxonRelationshipType relationshipType){
158
        Reference reference = classification.getReference();
159
    	Taxon cloneTaxon = (Taxon) HibernateProxyHelper.deproxy(originalParentNode.getTaxon(), Taxon.class).clone();
160
    	cloneTaxon.setSec(reference);
161
		String microReference = null;
162
		List<TaxonNode> originalChildNodes = originalParentNode.getChildNodes();
163
		HHH_9751_Util.removeAllNull(originalChildNodes);
164

  
165
		//add relation between taxa
166
		if (relationshipType != null){
167
		    cloneTaxon.addTaxonRelation(originalParentNode.getTaxon(), relationshipType, reference, microReference);
168
		}
188
    private void addChildTaxaToClone(TaxonNode originalParentNode, TaxonNode parentNodeClone,
189
            SubtreeCloneConfigurator config){
169 190

  
170
		TaxonNode cloneChildNode = null;
171
    	//add taxon node to either parent node or classification (no parent node)
172
    	if(cloneParentNode==null){
173
    		cloneChildNode = classification.addChildTaxon(cloneTaxon, reference, microReference);
174
    	}
175
    	else{
176
    		cloneChildNode = cloneParentNode.addChildTaxon(cloneTaxon, reference, microReference);
177
    	}
178
    	taxonNodeDao.saveOrUpdate(cloneChildNode);
179
    	//add children
180
		for (TaxonNode originalChildNode : originalChildNodes) {
181
    		addChildTaxa(originalChildNode, cloneChildNode, classification, relationshipType);
182
    	}
191
        Taxon originalTaxon = CdmBase.deproxy(originalParentNode.getTaxon());
192
        if (originalTaxon == null){
193
            for (TaxonNode originalChildChildNode : originalParentNode.getChildNodes()) {
194
                addChildTaxaToClone(originalChildChildNode, parentNodeClone, config);
195
            }
196
        }else{
197
            TaxonNode childNodeClone;
198
            String microReference = null;
199
            if (config.isReuseTaxa()){
200
                childNodeClone = parentNodeClone.addChildTaxon(originalTaxon, config.getParentChildReference(), microReference);
201
            }else{
202
                Taxon cloneTaxon = originalTaxon.clone(config.isCloneSynonyms(), config.isCloneTaxonRelationships(),
203
                        config.isCloneDescriptiveData(), config.isCloneMedia());
204
//                xxx KonzeptClone MAN, ppSyns;
205
                if (!config.isReuseTaxonSecundum()){
206
                    cloneTaxon.setSec(config.getTaxonSecundum());
207
                }
208

  
209
                //add relation between taxa
210
                if (config.getRelationTypeToOldTaxon() != null){
211
                    TaxonRelationship rel = cloneTaxon.addTaxonRelation(originalParentNode.getTaxon(), config.getRelationTypeToOldTaxon(),
212
                            config.getRelationshipReference(), microReference);
213
                    rel.setDoubtful(config.isRelationDoubtful());
214
                }
215
                childNodeClone = parentNodeClone.addChildTaxon(cloneTaxon, config.getParentChildReference(), microReference);
216
            }
217

  
218
            //TODO necessary?
219
            taxonNodeDao.saveOrUpdate(childNodeClone);
220
            //add children
221
            List<TaxonNode> originalChildNodes = originalParentNode.getChildNodes();
222
            HHH_9751_Util.removeAllNull(originalChildNodes);
223

  
224
            for (TaxonNode originalChildNode : originalChildNodes) {
225
                addChildTaxaToClone(originalChildNode, childNodeClone, config);
226
            }
227
        }
183 228
    }
184 229

  
185 230
    @Override
......
253 298
        return loadTreeBranch(taxonNode, null, baseRank, includeUnpublished, propertyPaths);
254 299
    }
255 300

  
256
    /**
257
     * {@inheritDoc}
258
     */
259 301
    @Override
260 302
    public List<TaxonNode> loadTreeBranch(TaxonNode taxonNode, TaxonNode subtree, Rank baseRank,
261 303
            boolean includeUnpublished, List<String> propertyPaths) throws UnpublishedException{
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IClassificationService.java
15 15
import java.util.UUID;
16 16

  
17 17
import eu.etaxonomy.cdm.api.service.config.CreateHierarchyForClassificationConfigurator;
18
import eu.etaxonomy.cdm.api.service.config.SubtreeCloneConfigurator;
18 19
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
19 20
import eu.etaxonomy.cdm.api.service.dto.GroupedTaxonDTO;
20 21
import eu.etaxonomy.cdm.api.service.dto.TaxonInContextDTO;
......
24 25
import eu.etaxonomy.cdm.model.common.MarkerType;
25 26
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
26 27
import eu.etaxonomy.cdm.model.name.Rank;
27
import eu.etaxonomy.cdm.model.reference.Reference;
28 28
import eu.etaxonomy.cdm.model.taxon.Classification;
29 29
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
30 30
import eu.etaxonomy.cdm.model.taxon.Taxon;
31 31
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
32
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
33 32
import eu.etaxonomy.cdm.persistence.dto.ClassificationLookupDTO;
34 33
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
35 34
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
......
42 41
 */
43 42
public interface IClassificationService extends IIdentifiableEntityService<Classification> {
44 43

  
45
    /**
46
     *
47
     * @param uuid
48
     * @return
49
     */
50 44
    public ITaxonTreeNode getTreeNodeByUuid(UUID uuid);
51 45

  
52 46
    /**
53
     *
54 47
     * Returns the root node of the the given classification (specified by its UUID)
55 48
     * @param classificationUuid the uuid of the classification
56 49
     * @return the root node of the classification
......
61 54

  
62 55
    /**
63 56
     * Clones an existing classification including all taxa and taxon nodes.
64
     * @param name
65
     * @param sec
66
     * @param relationshipType
67
     * @return
57

  
58
     * @param config the configurator for the cloning
68 59
     */
69
    public UpdateResult cloneClassification(UUID classificationUuid, String name, Reference sec, TaxonRelationshipType relationshipType);
60
    public UpdateResult cloneClassification(SubtreeCloneConfigurator config);
70 61

  
71 62
    /**
72 63
     *
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/SpecimenDeleteConfigurator.java
19 19
 */
20 20
public class SpecimenDeleteConfigurator extends DeleteConfiguratorBase {
21 21

  
22
    private static final long serialVersionUID = 5306732384161520246L;
23

  
22 24
    /**
23 25
     * If <code>true</code> all sub derivates of the specimen are deleted.
24 26
     */
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/SubtreeCloneConfigurator.java
1
/**
2
* Copyright (C) 2020 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
package eu.etaxonomy.cdm.api.service.config;
10

  
11
import java.io.Serializable;
12
import java.util.HashSet;
13
import java.util.Set;
14
import java.util.UUID;
15

  
16
import eu.etaxonomy.cdm.model.reference.Reference;
17
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
18
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
19

  
20
/**
21
 * @author a.mueller
22
 * @since 30.11.2020
23
 */
24
public class SubtreeCloneConfigurator implements Serializable {
25

  
26
    private static final long serialVersionUID = 5599009171476893297L;
27

  
28
    //might be replaced by a TaxonNodeFilter in future (but requires treebuilding and handling for missing inbetween taxa a tree)
29
    private Set<UUID> subTreeUuids;
30

  
31
    private String classificationName = "Taxon subtree clone";
32

  
33
    private boolean reuseClassificationReference = false;
34
     //used only if reuseClassificationReferenceUuid == false
35
     private UUID classificationReferenceUuid;
36
     private Reference classificationReference;
37

  
38
    private boolean reuseTaxa = false;
39
     //used only if reuseTaxa == false
40
     private boolean cloneSynonyms = true;
41
     //used only if reuseTaxa == false
42
     private boolean cloneDescriptiveData = true;
43
     //used only if reuseTaxa == false
44
     private boolean cloneMedia = true;
45
     //used only if reuseTaxa == false
46
     private boolean cloneTaxonRelationships = false;
47
     //used only if reuseTaxa == false
48
     private boolean reuseNames = true;
49
     //used only if reuseTaxa == false
50
     private boolean reuseTaxonSecundum = true;
51
      //used only if reuseTaxa == false AND reuseTaxonSecundum = false
52
      private UUID taxonSecundumUuid = null;
53
      private Reference taxonSecundum;
54

  
55
    private boolean reuseParentChildReference = true;
56
     //used only if reuseParentChildReference == false
57
     private UUID parentChildReferenceUuid = null;
58
     private Reference parentChildReference;
59

  
60
    private TaxonRelationshipType relationTypeToOldTaxon;
61
     //used only if relationTypeToOldTaxon != null
62
     private boolean relationDoubtful = true;
63
     //used only if relationTypeToOldTaxon != null
64
     private UUID relationshipReferenceUuid = null;
65
     private Reference relationshipReference;
66

  
67

  
68
    public static SubtreeCloneConfigurator NewBaseInstance(UUID subTreeUuid, String classificationName
69
            ){
70
        Set<UUID> subTreeUuids = new HashSet<>();
71
        subTreeUuids.add(subTreeUuid);
72
        return new SubtreeCloneConfigurator(subTreeUuids, classificationName,
73
                false, null,
74
                false, true, null,
75
                true, null,
76
                null,
77
                true
78
                );
79
    }
80

  
81
    public static SubtreeCloneConfigurator NewInstance(Set<UUID> subTreeUuids, String classificationName,
82
            boolean reuseClassificationReference, UUID classificationReferenceUuid, boolean reuseTaxa,
83
            boolean reuseTaxonSecundum, UUID taxonSecundumUuid, boolean reuseParentChildReference,
84
            UUID parentChildReferenceUuid, TaxonRelationshipType relationTypeToOldTaxon, boolean reuseNames){
85
        return new SubtreeCloneConfigurator(subTreeUuids, classificationName,
86
            reuseClassificationReference, classificationReferenceUuid,
87
            reuseTaxa, reuseTaxonSecundum, taxonSecundumUuid,
88
            reuseParentChildReference, parentChildReferenceUuid,
89
            relationTypeToOldTaxon,
90
            reuseNames);
91
    }
92

  
93

  
94
// ******************************** CONSTRUCTOR ********************************/
95

  
96
    private SubtreeCloneConfigurator(Set<UUID> subTreeUuids, String classificationName,
97
            boolean reuseClassificationReference, UUID classificationReferenceUuid,
98
            boolean reuseTaxa, boolean reuseTaxonSecundum, UUID taxonSecundumUuid,
99
            boolean reuseParentChildReference, UUID parentChildReferenceUuid,
100
            TaxonRelationshipType relationTypeToOldTaxon,
101
            boolean reuseNames) {
102
        this.subTreeUuids = subTreeUuids;
103
        this.classificationName = classificationName;
104
        this.reuseClassificationReference = reuseClassificationReference;
105
        this.classificationReferenceUuid = classificationReferenceUuid;
106
        this.reuseTaxa = reuseTaxa;
107
        this.reuseTaxonSecundum = reuseTaxonSecundum;
108
        this.taxonSecundumUuid = taxonSecundumUuid;
109
        this.reuseParentChildReference = reuseParentChildReference;
110
        this.parentChildReferenceUuid = parentChildReferenceUuid;
111
        this.relationTypeToOldTaxon = relationTypeToOldTaxon;
112
        this.reuseNames = reuseNames;
113
    }
114

  
115
// ******************** GETTER / SETTER ********************************/
116

  
117
    public Set<UUID> getSubTreeUuids() {
118
        return subTreeUuids;
119
    }
120
    public void setSubTreeUuids(Set<UUID> subTreeUuid) {
121
        this.subTreeUuids = subTreeUuid;
122
    }
123

  
124
    public String getClassificationName() {
125
        return classificationName;
126
    }
127
    public void setClassificationName(String classificationName) {
128
        this.classificationName = classificationName;
129
    }
130

  
131
    public UUID getClassificationReferenceUuid() {
132
        return classificationReferenceUuid;
133
    }
134
    public void setClassificationReferenceUuid(UUID classificationReferenceUuid) {
135
        this.classificationReferenceUuid = classificationReferenceUuid;
136
    }
137

  
138
    public UUID getTaxonSecundumUuid() {
139
        return taxonSecundumUuid;
140
    }
141
    public void setTaxonSecundumUuid(UUID taxonSecundumUuid) {
142
        this.taxonSecundumUuid = taxonSecundumUuid;
143
    }
144

  
145
    public UUID getParentChildReferenceUuid() {
146
        return parentChildReferenceUuid;
147
    }
148
    public void setParentChildReferenceUuid(UUID parentChildReferenceUuid) {
149
        this.parentChildReferenceUuid = parentChildReferenceUuid;
150
    }
151

  
152
    public TaxonRelationshipType getRelationTypeToOldTaxon() {
153
        return relationTypeToOldTaxon;
154
    }
155
    public void setRelationTypeToOldTaxon(TaxonRelationshipType relationTypeToOldTaxon) {
156
        this.relationTypeToOldTaxon = relationTypeToOldTaxon;
157
    }
158

  
159
    public boolean isReuseTaxa() {
160
        return reuseTaxa;
161
    }
162
    public void setReuseTaxa(boolean reuseTaxa) {
163
        this.reuseTaxa = reuseTaxa;
164
    }
165

  
166
    public boolean isReuseNames() {
167
        return reuseNames;
168
    }
169
    public void setReuseNames(boolean reuseNames) {
170
        this.reuseNames = reuseNames;
171
    }
172
    public boolean isReuseClassificationReference() {
173
        return reuseClassificationReference;
174
    }
175
    public void setReuseClassificationReference(boolean reuseClassificationReference) {
176
        this.reuseClassificationReference = reuseClassificationReference;
177
    }
178
    public boolean isReuseTaxonSecundum() {
179
        return reuseTaxonSecundum;
180
    }
181
    public void setReuseTaxonSecundum(boolean reuseTaxonSecundum) {
182
        this.reuseTaxonSecundum = reuseTaxonSecundum;
183
    }
184
    public boolean isReuseParentChildReference() {
185
        return reuseParentChildReference;
186
    }
187
    public void setReuseParentChildReference(boolean reuseParentChildReference) {
188
        this.reuseParentChildReference = reuseParentChildReference;
189
    }
190

  
191
    public boolean isRelationDoubtful() {
192
        return relationDoubtful;
193
    }
194

  
195
    public void setRelationDoubtful(boolean relationDoubtful) {
196
        this.relationDoubtful = relationDoubtful;
197
    }
198

  
199
    public UUID getRelationshipReferenceUuid() {
200
        return relationshipReferenceUuid;
201
    }
202

  
203
    public void setRelationshipReferenceUuid(UUID relationshipReferenceUuid) {
204
        this.relationshipReferenceUuid = relationshipReferenceUuid;
205
    }
206

  
207
    public Reference getClassificationReference() {
208
        return classificationReference;
209
    }
210

  
211
    /**
212
     * Sets the reference for the classification reference. Also the {@link #getClassificationReferenceUuid()
213
     * classification reference uuid} is set by this method.<BR>
214
     * This parameter is used only if <code>{@link #isReuseClassificationReference() reuse classification reference} == false</code>
215
     * <BR>
216
     * NOTE: Only use persistent references if configurator is not used within a single transaction.
217
     * @param parentChildReference
218
     */
219
    public void setClassificationReference(Reference classificationReference) {
220
        this.classificationReference = classificationReference;
221
    }
222

  
223
    public Reference getTaxonSecundum() {
224
        return taxonSecundum;
225
    }
226
    /**
227
     * Sets the taxon secundum reference. Also the {@link #getTaxonSecundumUuid() taxon secundum reference uuid} is set by this method.<BR>
228
     * This parameter is used only if <code>{@link #isReuseTaxa() reuseTaxa} == false && {@link #isReuseTaxonSecundum()
229
     * reuseTaxonSecundum} == false</code>
230
     * <BR>
231
     * NOTE: Only use persistent references if configurator is not used within a single transaction.
232
     * @param taxonSecundum
233
     */
234
    public void setTaxonSecundum(Reference taxonSecundum) {
235
        this.taxonSecundum = taxonSecundum;
236
        this.taxonSecundumUuid = taxonSecundum == null ? null : taxonSecundum.getUuid();
237
    }
238

  
239
    public Reference getParentChildReference() {
240
        return parentChildReference;
241
    }
242

  
243
    /**
244
     * Sets the reference for the parent child relationship. Also the {@link #getParentChildReferenceUuid()
245
     * parent child reference uuid} is set by this method.<BR>
246
     * This parameter is used only if <code>{@link #isReuseParentChildReference() reuse parent child reference} == false</code>
247
     * <BR>
248
     * NOTE: Only use persistent references if configurator is not used within a single transaction.
249
     * @param parentChildReference
250
     */
251
    public void setParentChildReference(Reference parentChildReference) {
252
        this.parentChildReference = parentChildReference;
253
    }
254

  
255
    public Reference getRelationshipReference() {
256
        return relationshipReference;
257
    }
258

  
259
    /**
260
     * Sets the reference for the new taxon to old taxon {@link TaxonRelationship taxon relationship}.
261
     * Also the {@link #getRelationshipReferenceUuid() relationship reference uuid} is set by this method.<BR>
262
     * This parameter is used only if <code>{@link #relationTypeToOldTaxon() relationTypeToOldTaxon} != null</code>
263
     * <BR>
264
     * NOTE: Only use persistent references if configurator is not used within a single transaction.
265
     * @param parentChildReference
266
     */
267
    public void setRelationshipReference(Reference relationshipReference) {
268
        this.relationshipReference = relationshipReference;
269
    }
270

  
271
    public boolean isCloneSynonyms() {
272
        return cloneSynonyms;
273
    }
274
    /**
275
     * If <code>true</code> the synonyms relationships of this taxon are cloned and attached to the new taxon.
276
     * <BR>
277
     * This parameter is used only if <code>{@link #isReuseTaxa() reuseTaxa} == false</code>
278
     */
279
    public void setCloneSynonyms(boolean cloneSynonyms) {
280
        this.cloneSynonyms = cloneSynonyms;
281
    }
282

  
283
    public boolean isCloneDescriptiveData() {
284
        return cloneDescriptiveData;
285
    }
286

  
287
    /**
288
     * If <code>true</code> the descriptive data attached to this taxon are also cloned and attached to the new taxon.
289
     * <BR>
290
     * This parameter is used only if <code>{@link #isReuseTaxa() reuseTaxa} == false</code>
291
     */
292
    public void setCloneDescriptiveData(boolean cloneDescriptiveData) {
293
        this.cloneDescriptiveData = cloneDescriptiveData;
294
    }
295

  
296
    public boolean isCloneMedia() {
297
        return cloneMedia;
298
    }
299
    /**
300
     * If <code>true</code> the media attached to this taxon are also attached to the new taxon.
301
     * Media itself are always reused.<BR>
302
     * This parameter is used only if <code>{@link #isReuseTaxa() reuseTaxa} == false</code>
303
     */
304
    public void setCloneMedia(boolean cloneMedia) {
305
        this.cloneMedia = cloneMedia;
306
    }
307

  
308
    public boolean isCloneTaxonRelationships() {
309
        return cloneTaxonRelationships;
310
    }
311
    /**
312
     * If <code>true</code> the taxon (concept) relationships to and from this taxon are also cloned.
313
     * <BR>
314
     * This parameter is used only if <code>{@link #isReuseTaxa() reuseTaxa} == false</code>
315
     */
316
    public void setCloneTaxonRelationships(boolean cloneTaxonRelationships) {
317
        this.cloneTaxonRelationships = cloneTaxonRelationships;
318
    }
319
}
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/SwitchAgentConfigurator.java
1
/**
2
* Copyright (C) 2014 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
*/
1 9
package eu.etaxonomy.cdm.api.service.config;
2 10

  
3 11
public class SwitchAgentConfigurator {
......
11 19
	public void setDoAddPersonAsMember(boolean doAddPersonAsMember) {
12 20
		this.doAddPersonAsMember = doAddPersonAsMember;
13 21
	}
14
	
15
	
16 22
}
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/ClassificationServiceImplTest.java
10 10
package eu.etaxonomy.cdm.api.service;
11 11

  
12 12
import static org.junit.Assert.assertEquals;
13
import static org.junit.Assert.assertNotNull;
13 14
import static org.junit.Assert.assertNull;
15
import static org.junit.Assert.assertTrue;
14 16

  
15 17
import java.io.FileNotFoundException;
16 18
import java.util.ArrayList;
......
20 22
import java.util.List;
21 23
import java.util.Set;
22 24
import java.util.UUID;
25
import java.util.stream.Collectors;
23 26

  
24 27
import org.apache.commons.lang.StringUtils;
25 28
import org.apache.log4j.Logger;
......
29 32
import org.unitils.dbunit.annotation.DataSet;
30 33
import org.unitils.spring.annotation.SpringBeanByType;
31 34

  
35
import eu.etaxonomy.cdm.api.service.config.SubtreeCloneConfigurator;
32 36
import eu.etaxonomy.cdm.api.service.dto.GroupedTaxonDTO;
33 37
import eu.etaxonomy.cdm.model.name.IBotanicalName;
34 38
import eu.etaxonomy.cdm.model.name.Rank;
......
39 43
import eu.etaxonomy.cdm.model.taxon.Taxon;
40 44
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41 45
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;
46
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
42 47
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
43 48
import eu.etaxonomy.cdm.persistence.dao.reference.IReferenceDao;
44 49
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
......
288 293
        Assert.assertFalse(StringUtils.isBlank(result.get(2).getGroupTaxonName()));
289 294
    }
290 295

  
291

  
292 296
    @Test
293 297
    @DataSet
294 298
    public final void testCloneClassification(){
295
    	Classification classification = classificationDao.load(CLASSIFICATION_UUID);
296
    	Reference sec = ReferenceFactory.newGeneric();
297
    	sec.setTitle("cloned sec");
298
    	Classification clone = (Classification) classificationService.cloneClassification(CLASSIFICATION_UUID, "Cloned classification", sec, TaxonRelationshipType.CONGRUENT_TO()).getCdmEntity();
299

  
300
    	List<TaxonNode> childNodes = classification.getChildNodes();
301
    	for (TaxonNode taxonNode : childNodes) {
302
			System.out.println(taxonNode.getTaxon().getTitleCache());
303
		}
304
    	childNodes = clone.getChildNodes();
305
    	for (TaxonNode taxonNode : childNodes) {
306
    		System.out.println(taxonNode.getTaxon().getTitleCache());
307
    	}
308
    	Set<TaxonNode> allNodes = classification.getAllNodes();
309
    	assertEquals("# of direct children does not match", classification.getChildNodes().size(), clone.getChildNodes().size());
310
		assertEquals("# of all nodes does not match", allNodes.size(), clone.getAllNodes().size());
311 299

  
312
    	//check that original taxon does not appear in cloned classification
313
		for (TaxonNode taxonNode : allNodes) {
314
    		assertNull(clone.getNode(taxonNode.getTaxon()));
300
    	Classification originalClassification = classificationDao.load(CLASSIFICATION_UUID);
301

  
302
    	SubtreeCloneConfigurator config = SubtreeCloneConfigurator.NewBaseInstance(
303
    	        originalClassification.getRootNode().getUuid(), "Cloned classification");
304

  
305
    	Classification classificatonClone = (Classification) classificationService.cloneClassification(config).getCdmEntity();
306

  
307
    	assertEquals("# of direct children does not match", originalClassification.getChildNodes().size(), classificatonClone.getChildNodes().size());
308
		assertEquals("# of all nodes does not match", originalClassification.getAllNodes().size(), classificatonClone.getAllNodes().size());
309

  
310
		Set<UUID> originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
311
    	for (TaxonNode clonedTaxonNode : classificatonClone.getChildNodes()) {
312
		    //test no reuse of taxon
313
		    Taxon clonedTaxon = clonedTaxonNode.getTaxon();
314
		    TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
315
    		assertNull(originalNode);
316

  
317
    		//check relationship
318
    		assertEquals(0, clonedTaxon.getRelationsFromThisTaxon().size());
319

  
320
    		//test taxon sec
321
    		assertTrue(originalTaxonSecUuids.contains(clonedTaxon.getSec().getUuid()));
315 322
    	}
323

  
324
    	//test reuse taxon
325
    	config.setReuseTaxa(true);
326
    	classificatonClone = (Classification) classificationService.cloneClassification(config).getCdmEntity();
327
    	assertEquals("# of direct children does not match", originalClassification.getChildNodes().size(), classificatonClone.getChildNodes().size());
328
    	originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
329
        for (TaxonNode taxonNode : classificatonClone.getChildNodes()) {
330
            //test no reuse of taxon
331
            Taxon clonedTaxon = taxonNode.getTaxon();
332
            TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
333
            assertNotNull(originalNode);
334
            Taxon originalTaxon = originalNode.getTaxon();
335
            assertNotNull(originalTaxon);
336

  
337
            //check relationship
338
            assertEquals(0, clonedTaxon.getRelationsFromThisTaxon().size());
339

  
340
            //test taxon sec
341
            assertEquals(originalTaxon.getSec().getUuid(), clonedTaxon.getSec().getUuid());
342
        }
343

  
344
        config.setReuseTaxa(false);  //reset
345
	    config.setRelationTypeToOldTaxon(TaxonRelationshipType.CONGRUENT_TO());
346
	    Reference sec = referenceDao.findByUuid(UUID.fromString("719d136b-409e-40d0-9561-46f6999465b4"));
347
	    config.setTaxonSecundumUuid(sec.getUuid());
348
	    classificatonClone = (Classification) classificationService.cloneClassification(config).getCdmEntity();
349
	    originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
350
        for (TaxonNode taxonNode : classificatonClone.getChildNodes()) {
351
            //test no reuse of taxon
352
            Taxon clonedTaxon = taxonNode.getTaxon();
353
            TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
354
            assertNull(originalNode);
355

  
356
            //check relationship
357
            TaxonRelationship relShip = clonedTaxon.getRelationsFromThisTaxon().iterator().next();
358
            Taxon relatedTaxon = relShip.getToTaxon();
359
            Taxon relatedOriginalTaxon = originalClassification.getNode(relatedTaxon).getTaxon();
360
            assertEquals(relatedOriginalTaxon.getName(), clonedTaxon.getName());
361
            assertTrue(relShip.getType().equals(TaxonRelationshipType.CONGRUENT_TO()));
362

  
363
            //test taxon sec
364
            assertEquals(relatedOriginalTaxon.getSec().getUuid(), clonedTaxon.getSec().getUuid());
365
        }
316 366
    }
317 367

  
318 368

  
......
320 370
    private UUID acacia_cuspidifolia_uuid = UUID.fromString("94123e4d-da49-4ed0-9d59-f52a9f7a3618");
321 371
    private UUID acacia_sect_botrycephalae_uuid = UUID.fromString("2c73a166-35d1-483d-b8e8-209214cb6193");
322 372

  
323

  
324
    /**
325
     * {@inheritDoc}
326
     */
327 373
    @Override
328 374
//    @Test
329 375
    public void createTestDataSet() throws FileNotFoundException {
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/ClassificationServiceImplTest.xml
17 17
  <TAXONNAME NAMETYPE="ICNAFP" ID="5006" CREATED="2015-09-03 10:40:10.0" UUID="1de1a72b-aa0a-4d8f-b434-97379a9fc4bf" UPDATED="2015-09-03 10:40:10.848" LSID_AUTHORITY="[null]" LSID_LSID="[null]" LSID_NAMESPACE="[null]" LSID_OBJECT="[null]" LSID_REVISION="[null]" PROTECTEDTITLECACHE="false" TITLECACHE="Acacia cuspidifolia Maslin" APPENDEDPHRASE="[null]" FULLTITLECACHE="Acacia cuspidifolia Maslin, Sp. Pl." NOMENCLATURALMICROREFERENCE="[null]" PARSINGPROBLEM="0" PROBLEMENDS="-1" PROBLEMSTARTS="-1" PROTECTEDFULLTITLECACHE="false" AUTHORSHIPCACHE="Maslin" BINOMHYBRID="false" GENUSORUNINOMIAL="Acacia" HYBRIDFORMULA="false" INFRAGENERICEPITHET="[null]" INFRASPECIFICEPITHET="[null]" MONOMHYBRID="false" NAMECACHE="Acacia cuspidifolia" PROTECTEDAUTHORSHIPCACHE="true" PROTECTEDNAMECACHE="false" SPECIFICEPITHET="cuspidifolia" TRINOMHYBRID="false" NAMEAPPROBATION="[null]" SUBGENUSAUTHORSHIP="[null]" ANAMORPHIC="false" CULTIVARNAME="[null]" ACRONYM="[null]" BREED="[null]" ORIGINALPUBLICATIONYEAR="[null]" PUBLICATIONYEAR="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" HOMOTYPICALGROUP_ID="5006" NOMENCLATURALREFERENCE_ID="5000" RANK_ID="765" BASIONYMAUTHORSHIP_ID="[null]" COMBINATIONAUTHORSHIP_ID="[null]" EXBASIONYMAUTHORSHIP_ID="[null]" EXCOMBINATIONAUTHORSHIP_ID="[null]"/>
18 18
  <TAXONNAME NAMETYPE="ICNAFP" ID="5007" CREATED="2015-09-03 10:40:10.0" UUID="3498c017-e8d1-43e0-9cb8-9edbdbe6f403" UPDATED="2015-09-03 10:40:10.851" LSID_AUTHORITY="[null]" LSID_LSID="[null]" LSID_NAMESPACE="[null]" LSID_OBJECT="[null]" LSID_REVISION="[null]" PROTECTEDTITLECACHE="false" TITLECACHE="Acacia acicularis Willd." APPENDEDPHRASE="[null]" FULLTITLECACHE="Acacia acicularis Willd., Sp. Pl." NOMENCLATURALMICROREFERENCE="[null]" PARSINGPROBLEM="0" PROBLEMENDS="-1" PROBLEMSTARTS="-1" PROTECTEDFULLTITLECACHE="false" AUTHORSHIPCACHE="Willd." BINOMHYBRID="false" GENUSORUNINOMIAL="Acacia" HYBRIDFORMULA="false" INFRAGENERICEPITHET="[null]" INFRASPECIFICEPITHET="[null]" MONOMHYBRID="false" NAMECACHE="Acacia acicularis" PROTECTEDAUTHORSHIPCACHE="true" PROTECTEDNAMECACHE="false" SPECIFICEPITHET="acicularis" TRINOMHYBRID="false" NAMEAPPROBATION="[null]" SUBGENUSAUTHORSHIP="[null]" ANAMORPHIC="false" CULTIVARNAME="[null]" ACRONYM="[null]" BREED="[null]" ORIGINALPUBLICATIONYEAR="[null]" PUBLICATIONYEAR="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" HOMOTYPICALGROUP_ID="5007" NOMENCLATURALREFERENCE_ID="5000" RANK_ID="765" BASIONYMAUTHORSHIP_ID="[null]" COMBINATIONAUTHORSHIP_ID="[null]" EXBASIONYMAUTHORSHIP_ID="[null]" EXCOMBINATIONAUTHORSHIP_ID="[null]"/>
19 19
  <REFERENCE ID="5000" CREATED="2015-09-03 10:40:10.0" UUID="d8db2b51-cb22-40ad-90e2-f66fa1306639" UPDATED="[null]" LSID_AUTHORITY="[null]" LSID_LSID="[null]" LSID_NAMESPACE="[null]" LSID_OBJECT="[null]" LSID_REVISION="[null]" PROTECTEDTITLECACHE="true" TITLECACHE="Sp. Pl." DATEPUBLISHED_END="[null]" DATEPUBLISHED_FREETEXT="[null]" DATEPUBLISHED_START="[null]" EDITION="[null]" EDITOR="[null]" ISBN="[null]" ISSN="[null]" DOI="[null]" NOMENCLATURALLYRELEVANT="false" ORGANIZATION="[null]" PAGES="[null]" PARSINGPROBLEM="0" PLACEPUBLISHED="[null]" PROBLEMENDS="-1" PROBLEMSTARTS="-1" PUBLISHER="[null]" REFERENCEABSTRACT="[null]" SERIESPART="[null]" TITLE="[null]" ABBREVTITLE="[null]" ABBREVTITLECACHE="" PROTECTEDABBREVTITLECACHE="false" REFTYPE="BK" URI="[null]" VOLUME="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" AUTHORSHIP_ID="[null]" INREFERENCE_ID="[null]" INSTITUTION_ID="[null]" SCHOOL_ID="[null]"/>
20
  <REFERENCE ID="5001" UUID="719d136b-409e-40d0-9561-46f6999465b4" PROTECTEDTITLECACHE="true" TITLECACHE="Classification reference" NOMENCLATURALLYRELEVANT="false" PARSINGPROBLEM="0" PROBLEMENDS="-1" PROBLEMSTARTS="-1" ABBREVTITLECACHE="" PROTECTEDABBREVTITLECACHE="false" REFTYPE="BK" />
21
  <REFERENCE ID="5002" UUID="b6bda80a-99f8-40a4-a810-21c9f717aa1b" PROTECTEDTITLECACHE="true" TITLECACHE="Taxon relation reference" NOMENCLATURALLYRELEVANT="false" PARSINGPROBLEM="0" PROBLEMENDS="-1" PROBLEMSTARTS="-1" ABBREVTITLECACHE="" PROTECTEDABBREVTITLECACHE="false" REFTYPE="BK" />
20 22
  <CLASSIFICATION ID="5000" CREATED="2015-09-03 10:40:10.0" UUID="6c2bc8d9-ee62-4222-be89-4a8e31770878" UPDATED="[null]" LSID_AUTHORITY="[null]" LSID_LSID="[null]" LSID_NAMESPACE="[null]" LSID_OBJECT="[null]" LSID_REVISION="[null]" PROTECTEDTITLECACHE="false" TITLECACHE="Acacia Classification" MICROREFERENCE="[null]" TIMEPERIOD_START="[null]" TIMEPERIOD_FREETEXT="[null]" TIMEPERIOD_END="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" NAME_ID="5000" REFERENCE_ID="[null]" ROOTNODE_ID="5000"/>
21 23
  <TAXONNODE ID="5000" CREATED="2015-09-03 10:40:10.0" UUID="6b4966ae-8815-49e5-849c-7001b29e5ed0" UPDATED="2015-09-03 10:40:10.8" SORTINDEX="-1" TREEINDEX="#t5000#5000#" COUNTCHILDREN="2" MICROREFERENCEFORPARENTCHILDRELATION="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" CLASSIFICATION_ID="5000" PARENT_ID="[null]" REFERENCEFORPARENTCHILDRELATION_ID="[null]" SYNONYMTOBEUSED_ID="[null]" TAXON_ID="[null]"/>
22 24
  <TAXONNODE ID="5001" CREATED="2015-09-03 10:40:10.0" UUID="26cc5c08-72df-45d4-84ea-ce81e7e53114" UPDATED="2015-09-03 10:40:10.827" SORTINDEX="0" TREEINDEX="#t5000#5000#5001#" COUNTCHILDREN="4" MICROREFERENCEFORPARENTCHILDRELATION="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" CLASSIFICATION_ID="5000" PARENT_ID="5000" REFERENCEFORPARENTCHILDRELATION_ID="5000" SYNONYMTOBEUSED_ID="[null]" TAXON_ID="5000"/>

Also available in: Unified diff