Merge branch 'release/5.44.0'
[cdmlib.git] / cdmlib-services / src / test / java / eu / etaxonomy / cdm / api / service / TaxonNodeServiceImplTest.java
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 package eu.etaxonomy.cdm.api.service;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertTrue;
16
17 import java.io.FileNotFoundException;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Set;
24 import java.util.UUID;
25 import java.util.stream.Collectors;
26
27 import org.junit.Assert;
28 import org.junit.Ignore;
29 import org.junit.Test;
30 import org.unitils.dbunit.annotation.DataSet;
31 import org.unitils.spring.annotation.SpringBeanByType;
32
33 import eu.etaxonomy.cdm.api.service.config.PublishForSubtreeConfigurator;
34 import eu.etaxonomy.cdm.api.service.config.SecundumForSubtreeConfigurator;
35 import eu.etaxonomy.cdm.api.service.config.SubtreeCloneConfigurator;
36 import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTO;
37 import eu.etaxonomy.cdm.compare.taxon.TaxonNodeNaturalComparator;
38 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
39 import eu.etaxonomy.cdm.model.common.CdmBase;
40 import eu.etaxonomy.cdm.model.description.PolytomousKey;
41 import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;
42 import eu.etaxonomy.cdm.model.metadata.DistributionDescription;
43 import eu.etaxonomy.cdm.model.metadata.SecReferenceHandlingEnum;
44 import eu.etaxonomy.cdm.model.name.IBotanicalName;
45 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
46 import eu.etaxonomy.cdm.model.name.Rank;
47 import eu.etaxonomy.cdm.model.name.TaxonName;
48 import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
49 import eu.etaxonomy.cdm.model.reference.Reference;
50 import eu.etaxonomy.cdm.model.taxon.Classification;
51 import eu.etaxonomy.cdm.model.taxon.Synonym;
52 import eu.etaxonomy.cdm.model.taxon.SynonymType;
53 import eu.etaxonomy.cdm.model.taxon.Taxon;
54 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
55 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
56 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
57 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
58 import eu.etaxonomy.cdm.persistence.dao.reference.IReferenceDao;
59 import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
60 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
61 import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
62 import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
63
64 /**
65 * @author n.hoffmann
66 * @since Dec 16, 2010
67 */
68 public class TaxonNodeServiceImplTest extends CdmTransactionalIntegrationTest{
69
70 private static String[] tableNames = new String[]{"CLASSIFICATION","TAXONNODE"};
71
72 @SpringBeanByType
73 private ITaxonNodeService taxonNodeService;
74
75 @SpringBeanByType
76 private IClassificationService classificationService;
77
78 @SpringBeanByType
79 private IReferenceService referenceService;
80
81 @SpringBeanByType
82 private IAgentService agentService;
83
84 @SpringBeanByType
85 private ITermService termService;
86
87 @SpringBeanByType
88 private INameService nameService;
89
90 @SpringBeanByType
91 private ITaxonService taxonService;
92
93 @SpringBeanByType
94 private IClassificationDao classificationDao;
95
96 @SpringBeanByType
97 private IReferenceDao referenceDao;
98
99 @SpringBeanByType
100 private IPolytomousKeyService polKeyService;
101
102 @SpringBeanByType
103 private IPolytomousKeyNodeService polKeyNodeService;
104
105 private static final UUID uuidRefNewSec = UUID.fromString("1d3fb074-d7ba-47e4-be94-b4cb1a99afa7");
106
107 private static final UUID t1Uuid = UUID.fromString("55c3e41a-c629-40e6-aa6a-ff274ac6ddb1");
108 private static final UUID t2Uuid = UUID.fromString("2659a7e0-ff35-4ee4-8493-b453756ab955");
109 private static final UUID classificationUuid = UUID.fromString("6c2bc8d9-ee62-4222-be89-4a8e31770878");
110 private static final UUID classification2Uuid = UUID.fromString("43d67247-936f-42a3-a739-bbcde372e334");
111 private static final UUID referenceUuid = UUID.fromString("de7d1205-291f-45d9-9059-ca83fc7ade14");
112 private static final UUID node1Uuid= UUID.fromString("484a1a77-689c-44be-8e65-347d835f47e8");
113 private static final UUID node2Uuid = UUID.fromString("2d41f0c2-b785-4f73-a436-cc2d5e93cc5b");
114
115 private static final UUID node4Uuid = UUID.fromString("2fbf7bf5-22dd-4c1a-84e4-c8c93d1f0342");
116 private static final UUID node5Uuid = UUID.fromString("c4d5170a-7967-4dac-ab76-ae2019eefde5");
117 private static final UUID node6Uuid = UUID.fromString("b419ba5e-9c8b-449c-ad86-7abfca9a7340");
118 private static final UUID rootNodeUuid = UUID.fromString("324a1a77-689c-44be-8e65-347d835f4111");
119 private static final UUID person1uuid = UUID.fromString("fe660517-8d8e-4dac-8bbb-4fb8f4f4a72e");
120
121 private Taxon t1;
122 private Taxon t2;
123 private Taxon t4;
124 private SynonymType synonymType;
125 private Reference reference;
126 private String referenceDetail;
127 private Classification classification;
128 private TaxonNode node1;
129 private TaxonNode node2;
130
131 private TaxonNode node4;
132
133 @Test
134 @DataSet
135 public final void testMakeTaxonNodeASynonymOfAnotherTaxonNode() {
136 classification = classificationService.load(classificationUuid);
137 node1 = taxonNodeService.load(node1Uuid);
138 node2 = taxonNodeService.load(node2Uuid);
139 node4 = taxonNodeService.load(node4Uuid);
140 reference = referenceService.load(referenceUuid);
141 synonymType = SynonymType.HOMOTYPIC_SYNONYM_OF;
142 referenceDetail = "test";
143
144 //TODO
145
146 // descriptions
147 t1 = node1.getTaxon();
148 PolytomousKey polKey = PolytomousKey.NewInstance();
149 PolytomousKeyNode keyNode = PolytomousKeyNode.NewInstance("", "", t1, null);
150 keyNode.setKey(polKey);
151 polKeyNodeService.save(keyNode);
152 polKeyService.save(polKey);
153
154 //nameRelations
155
156 TaxonName relatedName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
157 t1.getName().addRelationshipFromName(relatedName, NameRelationshipType.ALTERNATIVE_NAME(), null, null );
158
159 //taxonRelations
160 Taxon relatedTaxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
161 t1.addTaxonRelation(relatedTaxon, TaxonRelationshipType.CONGRUENT_OR_EXCLUDES(), null, null);
162 Synonym synonym = Synonym.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
163 taxonService.save(t1);
164 taxonService.save(relatedTaxon);
165 nameService.save(relatedName);
166
167 t1.addHomotypicSynonym(synonym);
168 taxonService.saveOrUpdate(t1);
169 t1 =(Taxon) taxonService.load(t1.getUuid());
170 t1 = HibernateProxyHelper.deproxy(t1);
171 TaxonName nameT1 = t1.getName();
172 t2 = node2.getTaxon();
173 assertEquals(2, t1.getDescriptions().size());
174 Assert.assertTrue(t2.getSynonyms().isEmpty());
175 Assert.assertTrue(t2.getDescriptions().size() == 0);
176 assertEquals(2,t1.getSynonyms().size());
177 DeleteResult result;
178
179 t4 = node4.getTaxon();
180 UUID uuidT4 = t4.getUuid();
181 t4 = (Taxon) taxonService.find(uuidT4);
182 TaxonName name4 = nameService.find(t4.getName().getUuid());
183 result = taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(node4, node2, synonymType, reference, referenceDetail, null, true);
184 if (result.isError() || result.isAbort()){
185 Assert.fail();
186 }
187 t4 = (Taxon)taxonService.find(uuidT4);
188 assertNull(t4);
189
190 //Taxon can't be deleted because of the polytomous key node
191 result = taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(node1, node2, synonymType, reference, referenceDetail,null, true);
192 if (result.isError() || result.isAbort()){
193 Assert.fail();
194 }
195 commitAndStartNewTransaction(new String[]{/*"TaxonNode"*/});
196 t1 = (Taxon)taxonService.find(t1Uuid);
197 assertNotNull(t1);//because of the polytomous key node
198 node1 = taxonNodeService.load(node1Uuid);
199 assertNull(node1);
200
201 Set<CdmBase> updatedObjects = result.getUpdatedObjects();
202 Iterator<CdmBase> it = updatedObjects.iterator();
203 Taxon taxon;
204 while (it.hasNext()) {
205 CdmBase updatedObject = it.next();
206 if(updatedObject.isInstanceOf(Taxon.class)){
207 taxon = HibernateProxyHelper.deproxy(updatedObject, Taxon.class);
208 Set<Synonym> syns = taxon.getSynonyms();
209 assertNotNull(syns);
210 if (taxon.equals(t2)){
211 assertEquals(4,syns.size());
212 Set<TaxonName> typifiedNames =taxon.getHomotypicGroup().getTypifiedNames();
213 assertEquals(typifiedNames.size(),4);
214 assertTrue(taxon.getHomotypicGroup().equals( nameT1.getHomotypicalGroup()));
215
216 assertEquals(taxon, t2);
217 }
218
219 }
220
221 }
222 }
223
224 /**
225 * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonNodeServiceImpl#makeTaxonNodeASynonymOfAnotherTaxonNode(eu.etaxonomy.cdm.model.taxon.TaxonNode, eu.etaxonomy.cdm.model.taxon.TaxonNode, eu.etaxonomy.cdm.model.taxon.SynonymType, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String)}.
226 */
227 @Test
228 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
229 public final void testMakeTaxonNodeAHeterotypicSynonymOfAnotherTaxonNode() {
230
231 //create data
232 classification = classificationService.load(classificationUuid);
233 node1 = taxonNodeService.load(node1Uuid);
234 node2 = taxonNodeService.load(node2Uuid);
235 reference = referenceService.load(referenceUuid);
236 synonymType = SynonymType.HETEROTYPIC_SYNONYM_OF;
237 referenceDetail = "test";
238
239 // descriptions
240 t1 = node1.getTaxon();
241 PolytomousKey polKey = PolytomousKey.NewInstance();
242 PolytomousKeyNode keyNode = PolytomousKeyNode.NewInstance("", "", t1, null);
243 keyNode.setKey(polKey);
244 polKeyNodeService.save(keyNode);
245 polKeyService.save(polKey);
246
247 //nameRelations
248 TaxonName relatedName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
249 t1.getName().addRelationshipFromName(relatedName, NameRelationshipType.ALTERNATIVE_NAME(), null, null );
250 TaxonName name1 = t1.getName();
251 UUID name1UUID = name1.getUuid();
252 //taxonRelations
253 Taxon relatedTaxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
254 t1.addTaxonRelation(relatedTaxon, TaxonRelationshipType.CONGRUENT_OR_EXCLUDES(), null, null);
255 Synonym t1HomotypSynonym = Synonym.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
256
257 t1.addHomotypicSynonym(t1HomotypSynonym);
258 TaxonName nameT1 = t1.getName();
259 t2 = node2.getTaxon();
260 assertEquals("taxon 1 must have 2 descriptions", 2, t1.getDescriptions().size());
261 assertEquals("taxon 1 must have 2 synonyms", 2, t1.getSynonyms().size());
262 Assert.assertTrue("taxon 2 must have no synonyms", t2.getSynonyms().isEmpty());
263 Assert.assertTrue("taxon 2 must have no descriptions", t2.getDescriptions().size() == 0);
264
265 //save
266 taxonService.save(t1HomotypSynonym);
267 taxonService.save(relatedTaxon);
268 nameService.save(relatedName);
269
270 //do it
271 DeleteResult result = taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode
272 (node1, node2, synonymType, reference, referenceDetail, null, true);
273
274 //post conditions
275 if (!result.getUpdatedObjects().iterator().hasNext()){
276 Assert.fail("Some updates must have taken place");
277 }
278 assertEquals(3, result.getUpdatedObjects().size());
279 assertNotNull("Old taxon should not have been deleted as it is referenced by key node", taxonService.find(t1Uuid));
280 assertNull("Old taxon node should not exist anymore", taxonNodeService.find(node1Uuid));
281
282 t1HomotypSynonym = (Synonym)taxonService.find(t1HomotypSynonym.getUuid());
283 assertNotNull(t1HomotypSynonym);
284
285 keyNode.setTaxon(null);
286 polKeyNodeService.saveOrUpdate(keyNode);
287 t2 =HibernateProxyHelper.deproxy(t2);
288 HibernateProxyHelper.deproxy(t2.getHomotypicGroup());
289 t2.setName(HibernateProxyHelper.deproxy(t2.getName()));
290
291 assertFalse("taxon 2 must have a synonym now", t2.getSynonyms().isEmpty());
292 assertEquals("taxon 2 must have 3 synonyms now, the old taxon 1 and it's 2 synonyms", 3, t2.getSynonyms().size());
293 assertEquals("taxon 2 must have 2 descriptions now, taken form taxon 1", 2, t2.getDescriptions().size());
294
295 result = taxonService.deleteTaxon(t1.getUuid(), null, null);
296 if (result.isAbort() || result.isError()){
297 Assert.fail();
298 }
299 assertNull(taxonService.find(t1Uuid));
300 assertNull(taxonNodeService.find(node1Uuid));
301 name1 = nameService.find(name1UUID);
302 assertNotNull("taxon name 1 should still exist", name1);
303 assertEquals("... but being used for the new synonym only as taxon 1 is deleted", 1, name1.getTaxonBases().size());
304 t1HomotypSynonym = (Synonym)taxonService.find(t1HomotypSynonym.getUuid());
305 assertNotNull(t1HomotypSynonym);
306
307 Synonym newSynonym =(Synonym) name1.getTaxonBases().iterator().next();
308
309 Taxon newAcceptedTaxon = CdmBase.deproxy(taxonService.find(t2.getUuid()), Taxon.class);
310 assertEquals("The new synonym (old accepted taxon) and it's homotypic synonym should still be homotypic", newSynonym.getHomotypicGroup(), t1HomotypSynonym.getName().getHomotypicalGroup());
311 assertFalse("The new accepted taxon must not be homotypic to ", newAcceptedTaxon.getHomotypicGroup().equals(newSynonym.getName().getHomotypicalGroup()));
312
313 assertEquals("The new accepted taxon is taxon 2", newAcceptedTaxon, t2);
314 assertEquals("The new synonyms name must be the same as the old accepted taxon's name", newSynonym.getName(), nameT1);
315 }
316
317
318 @Test
319 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="TaxonNodeServiceImplTest-indexing.xml")
320 public final void testIndexCreateNode() {
321 Taxon taxon = Taxon.NewInstance(null, null);
322 classification = classificationService.load(classificationUuid);
323 node2 = taxonNodeService.load(node2Uuid);
324 String oldTreeIndex = node2.treeIndex();
325
326 TaxonNode newNode = node2.addChildTaxon(taxon, null, null);
327 taxonNodeService.saveOrUpdate(newNode);
328 commitAndStartNewTransaction(new String[]{"TaxonNode"});
329 newNode = taxonNodeService.load(newNode.getUuid());
330 Assert.assertEquals("", oldTreeIndex + newNode.getId() + "#", newNode.treeIndex());
331 }
332
333
334 @Test
335 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="TaxonNodeServiceImplTest-indexing.xml")
336 public final void testIndexMoveNode() {
337 //in classification
338 classification = classificationService.load(classificationUuid);
339 node1 = taxonNodeService.load(node1Uuid);
340 node2 = taxonNodeService.load(node2Uuid);
341 node2.addChildNode(node1, null, null);
342 taxonNodeService.saveOrUpdate(node1);
343 commitAndStartNewTransaction(new String[]{"TaxonNode"});
344 TaxonNode node6 = taxonNodeService.load(node6Uuid);
345 Assert.assertEquals("Node6 treeindex is not correct", node2.treeIndex() + "2#4#6#", node6.treeIndex());
346
347 //root of new classification
348 Classification classification2 = classificationService.load(classification2Uuid);
349 node1 = taxonNodeService.load(node1Uuid);
350 classification2.setRootNode(HibernateProxyHelper.deproxy(classification2.getRootNode(),TaxonNode.class));
351 classification2.addChildNode(node1, null, null);
352 taxonNodeService.saveOrUpdate(node1);
353 commitAndStartNewTransaction(new String[]{"TaxonNode"});
354 node1 = taxonNodeService.load(node1Uuid);
355 Assert.assertEquals("Node1 treeindex is not correct", "#t2#8#2#", node1.treeIndex());
356 node6 = taxonNodeService.load(node6Uuid);
357 Assert.assertEquals("Node6 treeindex is not correct", "#t2#8#2#4#6#", node6.treeIndex());
358
359 //into new classification
360 node2 = taxonNodeService.load(node2Uuid);
361 TaxonNode node5 = taxonNodeService.load(node5Uuid);
362 node2 =node5.addChildNode(node2, null, null);
363 taxonNodeService.saveOrUpdate(node2);
364 commitAndStartNewTransaction(new String[]{"TaxonNode"});
365 node2 = taxonNodeService.load(node2Uuid);
366 Assert.assertEquals("Node3 treeindex is not correct", "#t2#8#2#5#3#", node2.treeIndex());
367
368 }
369
370 @Test
371 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="TaxonNodeServiceImplTest-indexing.xml")
372 public final void testIndexDeleteNode() {
373 commitAndStartNewTransaction(new String[]{"TaxonNode"});
374 node1 = taxonNodeService.load(node1Uuid);
375 TaxonNode node4 = taxonNodeService.load(node4Uuid);
376 String treeIndex = node1.treeIndex();
377 TaxonNode node6 = taxonNodeService.load(node6Uuid);
378 treeIndex= node6.treeIndex();
379
380 HibernateProxyHelper.deproxy(node1, TaxonNode.class);
381 node1.deleteChildNode(node4, false);
382 TaxonNode node5 = taxonNodeService.load(node5Uuid);
383 treeIndex = node5.treeIndex();
384
385 node6 = taxonNodeService.load(node6Uuid);
386
387 treeIndex = node6.treeIndex();
388 Taxon newTaxon= Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
389 UUID taxonNewUuid = taxonService.save(newTaxon).getUuid();
390
391 node5.addChildTaxon(newTaxon, null, null);
392 String node5TreeIndex =node5.treeIndex();
393 taxonNodeService.saveOrUpdate(node5);
394
395 commitAndStartNewTransaction(new String[]{"TaxonNode"});
396 node5 = taxonNodeService.load(node5Uuid);
397 List<TaxonNode> children = node5.getChildNodes();
398 TaxonNode node = children.get(0);
399 int id = node.getId();
400 Assert.assertEquals("Node6 treeindex is not correct", "#t1#1#2#6#", treeIndex);
401 Assert.assertEquals("new node treeindex is not correct", node5TreeIndex + id +"#", node.treeIndex());
402 }
403
404
405 @Test
406 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
407 public final void testDeleteNode(){
408 classification = classificationService.load(classificationUuid);
409 node1 = taxonNodeService.load(node1Uuid);
410 node2 = taxonNodeService.load(rootNodeUuid);
411 node1 = HibernateProxyHelper.deproxy(node1);
412
413 TaxonNode newNode = node1.addChildTaxon(Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null), null, null);
414 UUID uuidNewNode = taxonNodeService.save(newNode).getUuid();
415 newNode = taxonNodeService.load(uuidNewNode);
416 UUID taxUUID = newNode.getTaxon().getUuid();
417 UUID nameUUID = newNode.getTaxon().getName().getUuid();
418
419 DeleteResult result = taxonNodeService.deleteTaxonNode(node1, null);
420 if (!result.isOk()){
421 Assert.fail();
422 }
423 newNode = taxonNodeService.load(uuidNewNode);
424 node1 = taxonNodeService.load(node1Uuid);
425 assertNull(newNode);
426 assertNull(node1);
427
428 t1 = (Taxon) taxonService.load(t1Uuid);
429 assertNull(t1);
430 Taxon newTaxon = (Taxon)taxonService.load(taxUUID);
431 assertNull(newTaxon);
432 IBotanicalName name = nameService.load(nameUUID);
433 assertNull(name);
434
435
436 }
437
438 @Test
439 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
440
441 public final void testDeleteNodeWithReusedTaxon(){
442 classification = classificationService.load(classificationUuid);
443 node1 = taxonNodeService.load(node1Uuid);
444 node2 = taxonNodeService.load(rootNodeUuid);
445 node1 = HibernateProxyHelper.deproxy(node1);
446
447
448 Classification classification2 = Classification.NewInstance("Classification2");
449 TaxonNode nodeClassification2 =classification2.addChildTaxon(node1.getTaxon(), null, null);
450 assertEquals(node1.getTaxon().getUuid(), t1Uuid);
451 classificationService.save(classification2);
452 List<TaxonNode> nodesOfClassification2 = taxonNodeService.listAllNodesForClassification(classification2, null, null);
453 UUID nodeUUID = nodesOfClassification2.get(0).getUuid();
454 assertEquals(nodeUUID, nodeClassification2.getUuid());
455 Taxon newTaxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
456 taxonService.save(newTaxon);
457 TaxonNode newNode = node1.addChildTaxon(newTaxon,null, null);
458 UUID uuidNewNode = taxonNodeService.save(newNode).getUuid();
459 newNode = taxonNodeService.load(uuidNewNode);
460 UUID taxUUID = newNode.getTaxon().getUuid();
461 UUID nameUUID = newNode.getTaxon().getName().getUuid();
462
463 DeleteResult result = taxonNodeService.deleteTaxonNode(node1, null);
464 if (!result.isOk()){
465 Assert.fail();
466 }
467 //taxonService.getSession().flush();
468 newNode = taxonNodeService.load(uuidNewNode);
469 node1 = taxonNodeService.load(node1Uuid);
470 assertNull(newNode);
471 assertNull(node1);
472 List<String> propertyPath = new ArrayList<>();
473 propertyPath.add("taxon.name.*");
474 nodeClassification2 =taxonNodeService.load(nodeUUID, propertyPath);
475 assertNotNull(nodeClassification2);
476 assertNotNull(nodeClassification2.getTaxon());
477 assertNotNull(nodeClassification2.getTaxon().getName());
478
479 t1 = (Taxon) taxonService.load(t1Uuid);
480 assertNotNull(t1);
481 newTaxon = (Taxon)taxonService.load(taxUUID);
482 assertNull(newTaxon);
483 IBotanicalName name = nameService.load(nameUUID);
484 assertNull(name);
485 }
486
487 @Test
488 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
489 public final void testDeleteNodes(){
490 classification = classificationService.load(classificationUuid);
491 node1 = taxonNodeService.load(node1Uuid);
492 node2 = taxonNodeService.load(rootNodeUuid);
493 node1 = HibernateProxyHelper.deproxy(node1);
494 node2 = HibernateProxyHelper.deproxy(node2);
495 TaxonNode newNode = node1.addChildTaxon(Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null), null, null);
496 UUID uuidNewNode = taxonNodeService.save(newNode).getUuid();
497 List<TaxonNode> treeNodes = new ArrayList<>();
498 treeNodes.add(node1);
499 treeNodes.add(node2);
500
501 taxonNodeService.deleteTaxonNodes(treeNodes, null);
502
503 newNode = taxonNodeService.load(uuidNewNode);
504 node1 = taxonNodeService.load(node1Uuid);
505 assertNull(newNode);
506 assertNull(node1);
507 //taxonService.getSession().flush();
508 t1 = (Taxon) taxonService.load(t1Uuid);
509 assertNull(t1);
510 t2 = (Taxon) taxonService.load(t2Uuid);
511 assertNull(t2);
512 }
513
514 @Test
515 @DataSet
516 public void testMoveTaxonNode(){
517 classification = classificationService.load(classificationUuid);
518 // Set<TaxonNode> nodes = classification.getAllNodes();
519 List<TaxonNode> nodes = classification.getChildNodes();
520 System.out.println(nodes.size());
521 classification.addChildTaxon(Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null), nodes.size(), null, null);
522 nodes = classification.getChildNodes();
523 System.out.println(nodes.size());
524 }
525
526 @Test
527 public void testCompareNaturalOrder() {
528 /*
529 * Classification
530 * * Abies
531 * `- Abies alba
532 * - Abies balsamea
533 * * Pinus
534 * `- Pinus pampa
535 */
536 Classification classification = Classification.NewInstance("Classification");
537 IBotanicalName abiesName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
538 abiesName.setGenusOrUninomial("Abies");
539 Taxon abies = Taxon.NewInstance(abiesName, null);
540 IBotanicalName abiesAlbaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
541 abiesAlbaName.setGenusOrUninomial("Abies");
542 abiesAlbaName.setSpecificEpithet("alba");
543 Taxon abiesAlba = Taxon.NewInstance(abiesAlbaName, null);
544 IBotanicalName pinusName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
545 pinusName.setGenusOrUninomial("Pinus");
546 Taxon pinus = Taxon.NewInstance(pinusName, null);
547 IBotanicalName pinusPampaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
548 pinusPampaName.setGenusOrUninomial("Pinus");
549 pinusPampaName.setSpecificEpithet("pampa");
550 Taxon pinusPampa = Taxon.NewInstance(pinusPampaName, null);
551
552 IBotanicalName abiesBalsameaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
553 abiesBalsameaName.setGenusOrUninomial("Abies");
554 abiesBalsameaName.setSpecificEpithet("balsamea");
555 Taxon abiesBalsamea = Taxon.NewInstance(abiesBalsameaName, null);
556
557 List<TaxonNode> nodes = new ArrayList<>();
558 nodes.add(classification.addChildTaxon(abies, null, null));
559 TaxonNode abiesAlbaNode = classification.addParentChild(abies, abiesAlba, null, null);
560 TaxonNode balsameaNode = classification.addParentChild(abies, abiesBalsamea, null, null);
561 nodes.add(balsameaNode);
562 nodes.add(abiesAlbaNode);
563 nodes.add(classification.addChildTaxon(pinus, null, null));
564 nodes.add(classification.addParentChild(pinus, pinusPampa, null, null));
565 this.taxonNodeService.save(nodes);
566 classificationService.saveClassification(classification);
567 commitAndStartNewTransaction();
568
569 classification = classificationDao.load(classification.getUuid());
570 TaxonNodeNaturalComparator comparator = new TaxonNodeNaturalComparator();
571 List<TaxonNode> allNodes = new ArrayList<>(classification.getAllNodes());
572 Collections.sort(allNodes, comparator);
573
574 Assert.assertEquals(allNodes.get(0).getTaxon(), abies );
575 Assert.assertEquals(allNodes.get(2).getTaxon(), abiesBalsamea );
576 Assert.assertEquals(allNodes.get(1).getTaxon(), abiesAlba );
577
578 taxonNodeService.moveTaxonNode(balsameaNode.getUuid(), abiesAlbaNode.getUuid(),1, SecReferenceHandlingEnum.KeepOrWarn, null);
579 commitAndStartNewTransaction();
580
581 classification = classificationService.load(classification.getUuid());
582 allNodes = new ArrayList<>(classification.getAllNodes());
583 Collections.sort(allNodes, comparator);
584
585 Assert.assertEquals(abies, allNodes.get(0).getTaxon());
586 Assert.assertEquals(abiesBalsamea, allNodes.get(1).getTaxon());
587 Assert.assertEquals(abiesAlba, allNodes.get(2).getTaxon());
588 }
589
590 @Test
591 @DataSet(loadStrategy = CleanSweepInsertLoadStrategy.class, value = "TaxonNodeServiceImplTest.testGetUuidAndTitleCacheHierarchy.xml")
592 public void testGetUuidAndTitleCacheHierarchy(){
593 UUID classificationUuid = UUID.fromString("029b4c07-5903-4dcf-87e8-406ed0e0285f");
594 UUID abiesUuid = UUID.fromString("f8306fd3-9825-41bf-94aa-a7b5790b553e");
595 UUID abiesAlbaUuid = UUID.fromString("c70f76e5-2dcb-41c5-ae6f-d756e0a0fae0");
596 UUID abiesAlbaSubBrotaUuid = UUID.fromString("06d58161-7707-44b5-b720-6c0eb916b37c");
597 UUID abiesPalmaUuid = UUID.fromString("6dfd30dd-e589-493a-b66a-19c4cb374f92");
598 UUID pinusUuid = UUID.fromString("5d8e8341-f5e9-4616-96cf-f0351dda42f4");
599 // /*
600 // * Checklist
601 // * - Abies
602 // * - Abies alba
603 // * - Abieas alba subs. brota
604 // * - Abies palma
605 // * -Pinus
606 // */
607 // Classification checklist = Classification.NewInstance("Checklist");
608 // checklist.setUuid(classificationUuid);
609 //
610 // BotanicalName abiesName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
611 // abiesName.setGenusOrUninomial("Abies");
612 // Taxon abies = Taxon.NewInstance(abiesName, null);
613 //
614 // BotanicalName abiesAlbaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
615 // abiesAlbaName.setGenusOrUninomial("Abies");
616 // abiesAlbaName.setSpecificEpithet("alba");
617 // Taxon abiesAlba = Taxon.NewInstance(abiesAlbaName, null);
618 //
619 // BotanicalName abiesAlbaSubBrotaName = TaxonNameFactory.NewBotanicalInstance(Rank.SUBSPECIES());
620 // abiesAlbaSubBrotaName.setGenusOrUninomial("Abies");
621 // abiesAlbaSubBrotaName.setSpecificEpithet("alba");
622 // abiesAlbaSubBrotaName.setInfraSpecificEpithet("brota");
623 // Taxon abiesAlbaSubBrota = Taxon.NewInstance(abiesAlbaSubBrotaName, null);
624 //
625 // BotanicalName abiesPalmaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
626 // abiesPalmaName.setGenusOrUninomial("Abies");
627 // abiesPalmaName.setSpecificEpithet("palma");
628 // Taxon abiesPalma = Taxon.NewInstance(abiesPalmaName, null);
629 //
630 // BotanicalName pinusName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
631 // pinusName.setGenusOrUninomial("Pinus");
632 // Taxon pinus = Taxon.NewInstance(pinusName, null);
633 //
634 // checklist.addParentChild(null, abies, null, null);
635 // checklist.addParentChild(abies, abiesAlba, null, null);
636 // checklist.addParentChild(abiesAlba, abiesAlbaSubBrota, null, null);
637 // checklist.addParentChild(abies, abiesPalma, null, null);
638 // checklist.addParentChild(null, pinus, null, null);
639 //
640 //
641 // setComplete();
642 // endTransaction();
643 //
644 // String fileNameAppendix = "testGetUuidAndTitleCacheHierarchy";
645 //
646 // writeDbUnitDataSetFile(new String[] {
647 // "TAXONBASE", "TAXONNAME",
648 // "TAXONRELATIONSHIP",
649 // "HOMOTYPICALGROUP",
650 // "CLASSIFICATION", "TAXONNODE",
651 // "HIBERNATE_SEQUENCES" // IMPORTANT!!!
652 // },
653 // fileNameAppendix );
654 Classification classification = classificationService.load(classificationUuid);
655
656 List<TaxonNode> expectedChildTaxonNodes = classification.getChildNodes();
657 List<TaxonNodeDto> childNodesUuidAndTitleCache = taxonNodeService.listChildNodesAsTaxonNodeDto(classification.getRootNode());
658 assertNotNull("child UuidAndTitleCache list is null", childNodesUuidAndTitleCache);
659
660 compareChildren(expectedChildTaxonNodes, childNodesUuidAndTitleCache);
661
662 //test taxon parent of sub species
663 Taxon abiesAlbaSubBrota = HibernateProxyHelper.deproxy(taxonService.load(abiesAlbaSubBrotaUuid), Taxon.class);
664 TaxonNode abiesAlbaSubBrotaNode = abiesAlbaSubBrota.getTaxonNodes().iterator().next();
665 TaxonNode expectedTaxonParent = HibernateProxyHelper.deproxy(abiesAlbaSubBrotaNode.getParent(), TaxonNode.class);
666 TaxonNodeDto taxonParent = taxonNodeService.getParentUuidAndTitleCache(abiesAlbaSubBrotaNode);
667 assertEquals("Taxon Nodes do not match. ", expectedTaxonParent.getUuid(), taxonParent.getUuid());
668 assertEquals("Taxon Nodes do not match. ", (Integer)expectedTaxonParent.getId(), taxonParent.getId());
669 assertEquals("Taxon Nodes do not match. ", expectedTaxonParent.getTaxon().getTitleCache(), taxonParent.getTitleCache());
670 assertEquals("Taxon Nodes do not match. ", expectedTaxonParent, taxonNodeService.load(taxonParent.getUuid()));
671
672 //test classification parent
673 Taxon abies = HibernateProxyHelper.deproxy(taxonService.load(abiesUuid), Taxon.class);
674 TaxonNode abiesNode = abies.getTaxonNodes().iterator().next();
675 TaxonNode expectedClassificationParent = HibernateProxyHelper.deproxy(abiesNode.getParent(), TaxonNode.class);
676 TaxonNodeDto classificationParent= taxonNodeService.getParentUuidAndTitleCache(abiesNode);
677 assertEquals("Taxon Nodes do not match. ", expectedClassificationParent.getUuid(), classificationParent.getUuid());
678 assertEquals("Taxon Nodes do not match. ", (Integer)expectedClassificationParent.getId(), classificationParent.getId());
679 assertEquals("Taxon Nodes do not match. ", expectedClassificationParent.getClassification().getTitleCache(), classificationParent.getTitleCache());
680 assertEquals("Taxon Nodes do not match. ", expectedClassificationParent, taxonNodeService.load(classificationParent.getUuid()));
681 }
682
683 private void compareChildren(List<TaxonNode> expectedChildTaxonNodes, List<TaxonNodeDto> childNodesDto){
684 assertEquals("Number of children does not match", expectedChildTaxonNodes.size(), childNodesDto.size());
685 TaxonNodeDto foundMatch = null;
686 for (TaxonNode taxonNode : expectedChildTaxonNodes) {
687 foundMatch = null;
688 for (TaxonNodeDto uuidAndTitleCache : childNodesDto) {
689 if(uuidAndTitleCache.getUuid().equals(taxonNode.getUuid())){
690 Taxon taxon = HibernateProxyHelper.deproxy(taxonNode.getTaxon(), Taxon.class);
691 String titleCache = taxon.getTitleCache();
692 if(uuidAndTitleCache.getTaxonTitleCache().equals(titleCache)){
693 foundMatch = uuidAndTitleCache;
694 break;
695 }
696 }
697 }
698 assertTrue(String.format("no matching UuidAndTitleCache found for child %s", taxonNode), foundMatch!=null);
699 compareChildren(taxonNode.getChildNodes(), taxonNodeService.listChildNodesAsTaxonNodeDto(foundMatch));
700 }
701 }
702 //
703 // private UuidAndTitleCache<TaxonNode> findMatchingUuidAndTitleCache(List<UuidAndTitleCache<TaxonNode>> childNodesUuidAndTitleCache,
704 // UuidAndTitleCache<TaxonNode> foundMatch, TaxonNode taxonNode) {
705 // for (UuidAndTitleCache<TaxonNode> uuidAndTitleCache : childNodesUuidAndTitleCache) {
706 // if(uuidAndTitleCache.getUuid().equals(taxonNode.getUuid())){
707 // String titleCache = taxonNode.getTaxon().getTitleCache();
708 // if(uuidAndTitleCache.getTitleCache().equals(titleCache)){
709 // foundMatch = uuidAndTitleCache;
710 // break;
711 // }
712 // }
713 // }
714 // return foundMatch;
715 // }
716
717 @Test
718 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
719 public void testSetSecundumForSubtree(){
720 Reference newSec = referenceService.find(uuidRefNewSec);
721 Reference refSpPl = referenceService.find(referenceUuid);
722
723 //assert current state
724 Assert.assertNotNull(newSec);
725 Assert.assertNull(taxonService.find(1).getSec());
726 Assert.assertNull(taxonService.find(2).getSec());
727 Assert.assertNull(taxonService.find(3).getSec());
728 Assert.assertNull(taxonService.find(4).getSec());
729 Taxon taxon5 = (Taxon)taxonService.find(5);
730 Assert.assertNotNull(taxon5.getSec());
731 Assert.assertNotEquals(newSec, taxon5.getSec());
732 Assert.assertNotNull(taxon5.getSecMicroReference());
733 Assert.assertEquals(1, taxon5.getMisappliedNameRelations().size());
734 Assert.assertEquals(refSpPl, taxon5.getMisappliedNameRelations().iterator().next().getSource().getCitation());
735 Assert.assertEquals(1, taxon5.getProParteAndPartialSynonymRelations().size());
736 Assert.assertNull(taxon5.getProParteAndPartialSynonymRelations().iterator().next().getSource());
737
738 //set secundum
739 SecundumForSubtreeConfigurator config = new SecundumForSubtreeConfigurator(node1Uuid, null, null, true);
740 config.setIncludeMisapplications(true);
741 config.setIncludeProParteSynonyms(true);
742 config.setNewSecundum(newSec);
743 UpdateResult result = taxonNodeService.setSecundumForSubtree(config);
744 Assert.assertTrue(result.getExceptions().isEmpty());
745 Assert.assertTrue(result.isOk());
746 Assert.assertEquals(6, result.getUpdatedObjects().size()); //should be 5 without workaround for #9627,#6359
747
748 commitAndStartNewTransaction(/*new String[]{"TaxonBase","TaxonBase_AUD"}*/);
749 Assert.assertEquals(newSec, taxonService.find(1).getSec());
750 Assert.assertNull(taxonService.find(2).getSec());
751 Assert.assertEquals(newSec, taxonService.find(3).getSec());
752 Assert.assertNull(taxonService.find(4).getSec());
753 taxon5 = (Taxon)taxonService.find(5);
754 Assert.assertEquals(newSec, taxon5.getSec());
755 Assert.assertNull(taxon5.getSecMicroReference());
756 Assert.assertEquals(newSec, taxon5.getMisappliedNameRelations().iterator().next().getSource().getCitation());
757 Assert.assertEquals(newSec, taxon5.getProParteAndPartialSynonymRelations().iterator().next().getSource().getCitation());
758 Taxon taxon2 = (Taxon)taxonService.find(2);
759 Assert.assertEquals(1, taxon2.getProParteAndPartialSynonymRelations().size());
760 Assert.assertNull(taxon2.getProParteAndPartialSynonymRelations().iterator().next().getSource());
761
762 result = taxonNodeService.setSecundumForSubtree(config);
763 Assert.assertTrue(result.getExceptions().isEmpty() && result.isOk());
764 Assert.assertEquals(0, result.getUpdatedObjects().size());
765
766 }
767
768 @Test
769 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
770 public void testSetSecundumForSubtreeNoOverwrite(){
771 Reference newSec = referenceService.find(uuidRefNewSec);
772 Reference refSpPl = referenceService.find(referenceUuid);
773
774 //assert current state
775 Assert.assertNotNull(newSec);
776 Assert.assertNull(taxonService.find(1).getSec());
777 Assert.assertNull(taxonService.find(2).getSec());
778 Assert.assertNull(taxonService.find(3).getSec());
779 Assert.assertNull(taxonService.find(4).getSec());
780 Taxon taxon5 = (Taxon)taxonService.find(5);
781 Assert.assertNotNull(taxon5.getSec());
782 Assert.assertNotEquals(newSec, taxon5.getSec());
783 Assert.assertNotNull(taxon5.getSecMicroReference());
784 Assert.assertEquals(1, taxon5.getMisappliedNameRelations().size());
785 Assert.assertEquals(refSpPl, taxon5.getMisappliedNameRelations().iterator().next().getSource().getCitation());
786 Assert.assertEquals(1, taxon5.getProParteAndPartialSynonymRelations().size());
787 Assert.assertNull(taxon5.getProParteAndPartialSynonymRelations().iterator().next().getSource());
788
789 //set secundum
790 SecundumForSubtreeConfigurator config = new SecundumForSubtreeConfigurator(node1Uuid, newSec, null, true);
791 config.setOverwriteExisting(false);
792 UpdateResult result = taxonNodeService.setSecundumForSubtree(config);
793 Assert.assertTrue(result.getExceptions().isEmpty());
794 Assert.assertTrue(result.isOk());
795 Assert.assertEquals(4, result.getUpdatedObjects().size()); //should be 3 without workaround for #9627,#6359
796
797 commitAndStartNewTransaction(); //new String[]{"TaxonBase","TaxonBase_AUD"}
798 Assert.assertEquals(newSec, taxonService.find(1).getSec());
799 Assert.assertNull(taxonService.find(2).getSec());
800 Assert.assertEquals(newSec, taxonService.find(3).getSec());
801 Assert.assertNull(taxonService.find(4).getSec());
802 Reference oldTaxon5Sec = taxon5.getSec();
803 taxon5 = (Taxon)taxonService.find(5);
804 Assert.assertEquals(oldTaxon5Sec, taxon5.getSec());
805 Assert.assertNotEquals(newSec, taxon5.getSec());
806 Assert.assertNotNull(taxon5.getSecMicroReference());
807 Assert.assertEquals("Should not override MAN source", refSpPl, taxon5.getMisappliedNameRelations().iterator().next().getSource().getCitation());
808 Assert.assertEquals(newSec, taxon5.getProParteAndPartialSynonymRelations().iterator().next().getSource().getCitation());
809 Taxon taxon2 = (Taxon)taxonService.find(2);
810 Assert.assertEquals("taxon2 is not part of subtree therefore should not be updated", 1, taxon2.getProParteAndPartialSynonymRelations().size());
811 Assert.assertNull(taxon2.getProParteAndPartialSynonymRelations().iterator().next().getSource());
812 }
813
814 @Test
815 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
816 public void testSetSecundumForSubtreeOnlyAccepted(){
817 Reference newSec = referenceService.find(uuidRefNewSec);
818
819 //assert current state
820 Assert.assertNotNull(newSec);
821 Assert.assertNull(taxonService.find(1).getSec());
822 Assert.assertNull(taxonService.find(2).getSec());
823 Assert.assertNull(taxonService.find(3).getSec());
824 Assert.assertNull(taxonService.find(4).getSec());
825 TaxonBase<?> taxon5 = taxonService.find(5);
826 Assert.assertNotNull(taxon5.getSec());
827 Assert.assertNotEquals(newSec, taxon5.getSec());
828 Assert.assertNotNull(taxon5.getSecMicroReference());
829
830 //set secundum
831 SecundumForSubtreeConfigurator config = new SecundumForSubtreeConfigurator(node1Uuid, newSec, null, false);
832 config.setIncludeSynonyms(false);
833 taxonNodeService.setSecundumForSubtree(config);
834
835 // commitAndStartNewTransaction(new String[]{"TaxonBase","TaxonBase_AUD"});
836 Assert.assertEquals(newSec, taxonService.find(1).getSec());
837 Assert.assertNull(taxonService.find(2).getSec());
838 Assert.assertNull(taxonService.find(3).getSec());
839 Assert.assertNull(taxonService.find(4).getSec());
840 taxon5 = taxonService.find(5);
841 Assert.assertEquals(newSec, taxon5.getSec());
842 Assert.assertNull(taxon5.getSecMicroReference());
843 }
844
845 @Test
846 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
847 public void testSetSecundumForSubtreeOnlySynonyms(){
848 Reference newSec = referenceService.find(uuidRefNewSec);
849
850 //assert current state
851 Assert.assertNotNull(newSec);
852 Assert.assertNull(taxonService.find(1).getSec());
853 Assert.assertNull(taxonService.find(2).getSec());
854 Assert.assertNull(taxonService.find(3).getSec());
855 Assert.assertNull(taxonService.find(4).getSec());
856 TaxonBase<?> taxon5 = taxonService.find(5);
857 Assert.assertNotNull(taxon5.getSec());
858 Assert.assertNotEquals(newSec, taxon5.getSec());
859 Assert.assertNotNull(taxon5.getSecMicroReference());
860
861 //set secundum
862 SecundumForSubtreeConfigurator config = new SecundumForSubtreeConfigurator(node1Uuid, newSec, null, false);
863 config.setIncludeAcceptedTaxa(false);
864 taxonNodeService.setSecundumForSubtree(config);
865
866 commitAndStartNewTransaction(new String[]{"TaxonBase","TaxonBase_AUD"});
867 Assert.assertNull(taxonService.find(1).getSec());
868 Assert.assertNull(taxonService.find(2).getSec());
869 Assert.assertEquals("Synonym should be updated", newSec, taxonService.find(3).getSec());
870 Assert.assertNull(taxonService.find(4).getSec());
871 Reference oldTaxon5Sec = taxon5.getSec();
872 taxon5 = taxonService.find(5);
873 Assert.assertEquals(oldTaxon5Sec, taxon5.getSec());
874 Assert.assertNotEquals(newSec, taxon5.getSec());
875 Assert.assertNotNull(taxon5.getSecMicroReference());
876 }
877
878 @Test
879 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
880 public void testSetSecundumForSubtreeNoShared(){
881 Reference newSec = referenceService.find(uuidRefNewSec);
882
883 //assert current state
884 Assert.assertNotNull(newSec);
885 Assert.assertNull(taxonService.find(1).getSec());
886 Assert.assertNull(taxonService.find(2).getSec());
887 Assert.assertNull(taxonService.find(3).getSec());
888 Assert.assertNull(taxonService.find(4).getSec());
889 Taxon taxon5 = (Taxon)taxonService.find(5);
890 Assert.assertNotNull(taxon5.getSec());
891 Assert.assertNotEquals(newSec, taxon5.getSec());
892 Assert.assertNotNull(taxon5.getSecMicroReference());
893 Taxon taxon1 = (Taxon)taxonService.find(1);
894 taxon1.addMisappliedName(taxon5, null, null);
895 Assert.assertEquals(1, taxon1.getMisappliedNameRelations().size());
896 commitAndStartNewTransaction();
897
898 //set secundum
899 SecundumForSubtreeConfigurator config = new SecundumForSubtreeConfigurator(node1Uuid, newSec, null, true);
900 config.setIncludeSharedTaxa(false);
901 taxonNodeService.setSecundumForSubtree(config);
902
903 commitAndStartNewTransaction(); //new String[]{"TaxonBase","TaxonBase_AUD"}
904 taxon1 = (Taxon)taxonService.find(1);
905 Assert.assertNull("Shared taxon must not be set", taxonService.find(1).getSec());
906 Assert.assertNull(taxonService.find(2).getSec());
907 Assert.assertNull("Synonym of shared taxon must not be set", taxonService.find(3).getSec());
908 Assert.assertNull(taxonService.find(4).getSec());
909 taxon5 = (Taxon)taxonService.find(5);
910 Assert.assertEquals(newSec, taxon5.getSec());
911 Assert.assertNull(taxon5.getSecMicroReference());
912 Assert.assertNull("without share no citation should be set", taxon1.getMisappliedNameRelations().iterator().next().getSource());
913 config.setIncludeSharedTaxa(true);
914 taxonNodeService.setSecundumForSubtree(config);
915 taxon1 = (Taxon)taxonService.find(1);
916 Assert.assertEquals("With shared taxa citation should be set", newSec, taxon1.getMisappliedNameRelations().iterator().next().getSource().getCitation());
917 }
918
919 @Test
920 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
921 public void testSetPublishForSubtree(){
922
923 assertStartingStateForSetPublish();
924
925 boolean publish = false;
926 PublishForSubtreeConfigurator config = PublishForSubtreeConfigurator.NewInstance(
927 node1Uuid, publish, null);
928 config.setIncludeAcceptedTaxa(true);
929 config.setIncludeSynonyms(true);
930 config.setIncludeSharedTaxa(true);
931 config.setIncludeHybrids(false);
932 taxonNodeService.setPublishForSubtree(config);
933
934 commitAndStartNewTransaction();
935
936 Assert.assertEquals(publish, taxonService.find(1).isPublish());
937 Assert.assertEquals("Taxon2 is not in subtree", true, taxonService.find(2).isPublish());
938 Assert.assertEquals("Synonym3 not yet updated because it is hybrid", true, taxonService.find(3).isPublish());
939 Assert.assertEquals("Synonym4 is not in subtree", true, taxonService.find(4).isPublish());
940 Assert.assertEquals(true, taxonService.find(5).isPublish());
941 Assert.assertEquals(publish, taxonService.find(6).isPublish());
942 Assert.assertEquals("Synonym7 is not in subtree", true, taxonService.find(7).isPublish());
943
944 config.setIncludeHybrids(true);
945 taxonNodeService.setPublishForSubtree(config);
946
947 commitAndStartNewTransaction();
948 Assert.assertEquals(publish, taxonService.find(3).isPublish());
949 Assert.assertEquals(publish, taxonService.find(5).isPublish());
950 Assert.assertEquals(publish, taxonService.find(7).isPublish());
951
952 }
953
954 @Test
955 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
956 public void testSetPublishForSubtreeOnlyAccepted(){
957
958 assertStartingStateForSetPublish();
959
960 boolean publish = false;
961 PublishForSubtreeConfigurator config = PublishForSubtreeConfigurator.NewInstance(node1Uuid, publish, null);
962 config.setIncludeAcceptedTaxa(true);
963 config.setIncludeSynonyms(false);
964 config.setIncludeMisapplications(false);
965 config.setIncludeProParteSynonyms(false);
966 config.setIncludeSharedTaxa(true);
967 taxonNodeService.setPublishForSubtree(config);
968
969
970 commitAndStartNewTransaction();
971 Assert.assertEquals(publish, taxonService.find(1).isPublish());
972 Assert.assertEquals("Taxon2 not in subtree", true, taxonService.find(2).isPublish());
973 Assert.assertEquals("Synonym3 should not be updated", true, taxonService.find(3).isPublish());
974 Assert.assertEquals("Synonym3 should not be updated", true, taxonService.find(4).isPublish());
975 Assert.assertEquals("Accepted in subtree should be udpated", publish, taxonService.find(5).isPublish());
976 Assert.assertEquals("Misapplied should not be updated", true, taxonService.find(6).isPublish());
977 Assert.assertEquals("Pro parte synonym should not be updated", true, taxonService.find(7).isPublish());
978
979 config.setIncludeMisapplications(true);
980 taxonNodeService.setPublishForSubtree(config);
981 commitAndStartNewTransaction();
982 Assert.assertEquals("Misapplied should be updated now", publish, taxonService.find(6).isPublish());
983 Assert.assertEquals("Pro parte synonym should not yet be updated", true, taxonService.find(7).isPublish());
984
985 config.setIncludeProParteSynonyms(true);
986 config.setIncludeHybrids(false);
987 taxonNodeService.setPublishForSubtree(config);
988 commitAndStartNewTransaction();
989 Assert.assertEquals("Pro parte synonym should not yet be updated because it is a hybrid", true, taxonService.find(7).isPublish());
990
991 config.setIncludeHybrids(true);
992 taxonNodeService.setPublishForSubtree(config);
993 commitAndStartNewTransaction();
994 Assert.assertEquals("Pro parte synonym should be updated now", publish, taxonService.find(7).isPublish());
995
996 }
997
998 @Test
999 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
1000 public void testSetPublishForSubtreeOnlySynonyms(){
1001
1002 //assert current state
1003 assertStartingStateForSetPublish();
1004
1005 boolean publish = false;
1006
1007 PublishForSubtreeConfigurator config = PublishForSubtreeConfigurator.NewInstance(
1008 node1Uuid, publish, null);
1009 config.setIncludeAcceptedTaxa(false);
1010 config.setIncludeSynonyms(true);
1011 config.setIncludeSharedTaxa(true); //should have no effect
1012 config.setIncludeMisapplications(false);
1013 config.setIncludeProParteSynonyms(false);
1014 taxonNodeService.setPublishForSubtree(config);
1015
1016 commitAndStartNewTransaction(new String[]{});
1017 Assert.assertEquals(true, taxonService.find(1).isPublish());
1018 Assert.assertEquals(true, taxonService.find(2).isPublish());
1019 //Synonym should be false
1020 Assert.assertEquals(publish, taxonService.find(3).isPublish());
1021 Assert.assertEquals(true, taxonService.find(4).isPublish());
1022 Assert.assertEquals(true, taxonService.find(5).isPublish());
1023 Assert.assertEquals(true, taxonService.find(6).isPublish());
1024 Assert.assertEquals(true, taxonService.find(7).isPublish());
1025
1026 config.setIncludeMisapplications(true);
1027 taxonNodeService.setPublishForSubtree(config);
1028 commitAndStartNewTransaction();
1029 Assert.assertEquals("Misapplied should be updated now", publish, taxonService.find(6).isPublish());
1030 Assert.assertEquals("Pro parte synonym should not yet be updated", true, taxonService.find(7).isPublish());
1031
1032 config.setIncludeProParteSynonyms(true);
1033 taxonNodeService.setPublishForSubtree(config);
1034 commitAndStartNewTransaction();
1035 Assert.assertEquals("Pro parte synonym should be updated now", publish, taxonService.find(7).isPublish());
1036
1037 }
1038
1039 private void assertStartingStateForSetPublish() {
1040 Assert.assertTrue(taxonService.find(1).isPublish());
1041 Assert.assertTrue(taxonService.find(2).isPublish());
1042 Assert.assertTrue(taxonService.find(3).isPublish());
1043 Assert.assertTrue(taxonService.find(4).isPublish());
1044 Assert.assertTrue(taxonService.find(5).isPublish());
1045 Assert.assertTrue(taxonService.find(6).isPublish());
1046 Assert.assertTrue(taxonService.find(7).isPublish());
1047 }
1048
1049
1050 @Test
1051 @DataSet("TaxonNodeServiceImplTest.testSetSecundumForSubtree.xml")
1052 public void testSetPublishForSubtreeNoShared(){
1053
1054 assertStartingStateForSetPublish();
1055
1056 boolean publish = false;
1057 PublishForSubtreeConfigurator config = PublishForSubtreeConfigurator.NewInstance(
1058 node1Uuid, publish, null);
1059 config.setIncludeAcceptedTaxa(true);
1060 config.setIncludeSynonyms(true);
1061 config.setIncludeSharedTaxa(false);
1062 taxonNodeService.setPublishForSubtree(config);
1063
1064 commitAndStartNewTransaction();
1065 Assert.assertEquals("Shared taxon must not be set", true, taxonService.find(1).isPublish());
1066 Assert.assertEquals("Taxon2 is not in subtree", true, taxonService.find(2).isPublish());
1067 Assert.assertEquals("Synonym of shared taxon must not be set", true, taxonService.find(3).isPublish());
1068 Assert.assertEquals("Synonym4 belongs to Taxon2 which is not in subtree", true, taxonService.find(4).isPublish());
1069 Assert.assertEquals("Taxon5 is in subtree and not shared => should be set to unpublished", publish, taxonService.find(5).isPublish());
1070 Assert.assertEquals("Misapplied exists as taxon in classification 2 and should not be updated"
1071 + " though related to taxon 5 which is updated", true, taxonService.find(6).isPublish());
1072 Assert.assertEquals("Pro parte synonym7 should not be updated, as it is "
1073 + "related to updated taxon5 but also to taxon2 which is not updated because not in subtree",
1074 true, taxonService.find(7).isPublish());
1075
1076 taxonService.find(2).setPublish(false);
1077 taxonNodeService.setPublishForSubtree(config);
1078 commitAndStartNewTransaction();
1079 Assert.assertEquals("Pro parte synonym7 should be updated now, as taxon2 is now unpublished"
1080 + " and therefore the noShared function is not relevant anymore",
1081 publish, taxonService.find(7).isPublish());
1082 }
1083
1084
1085 @Test
1086 @DataSet("TaxonNodeServiceImplTest.xml")
1087 public void testGetTaxonDistributionDTO(){
1088 List<UUID> uuidList = Arrays.asList(node1Uuid, node2Uuid, node4Uuid);
1089 List<TaxonDistributionDTO> dtos = this.taxonNodeService.getTaxonDistributionDTO(uuidList, null, true, DistributionDescription.UseAlreadyExisting);
1090 Assert.assertEquals("Children should be deduplicated", 3, dtos.size());
1091 //note: the following ordering is not given by definition (as the method does not guarantee a certain order)
1092 // but is used as pseudo test here for the correctnes of the algorithm as it is currently expected
1093 Assert.assertEquals("First node comes first", node1Uuid, dtos.get(0).getTaxonNodeDto().getUuid());
1094 Assert.assertEquals("Child of first node comes second", node4Uuid, dtos.get(1).getTaxonNodeDto().getUuid());
1095 Assert.assertEquals("Second node comes third", node2Uuid, dtos.get(2).getTaxonNodeDto().getUuid());
1096 //third node is child of firt node and therefore came second already
1097 }
1098
1099 @Test
1100 @DataSet("TaxonNodeServiceImplTest-testFindCommonParentNode.xml")
1101 public void testFindCommonParentNode(){
1102 UUID checklist2Uuid = UUID.fromString("c6e3a598-3b6c-4ef5-8b01-5bdb3de5a9fd");
1103 UUID campanulaNodeUuid = UUID.fromString("62fa918d-a1d8-4284-ae4b-93478bde8656");
1104 UUID campanulaPersicifoliaNodeUuid = UUID.fromString("dce3defa-5123-44a7-8008-0cc9b27461f6");
1105
1106 UUID classificationUuid = UUID.fromString("029b4c07-5903-4dcf-87e8-406ed0e0285f");
1107 UUID abiesNodeUuid = UUID.fromString("f8306fd3-9825-41bf-94aa-a7b5790b553e");
1108 UUID abiesAlbaNodeUuid = UUID.fromString("c70f76e5-2dcb-41c5-ae6f-d756e0a0fae0");
1109 UUID abiesAlbaSubBrotaNodeUuid = UUID.fromString("06d58161-7707-44b5-b720-6c0eb916b37c");
1110 UUID abiesPalmaNodeUuid = UUID.fromString("6dfd30dd-e589-493a-b66a-19c4cb374f92");
1111
1112 UUID pinusNodeUuid = UUID.fromString("5d8e8341-f5e9-4616-96cf-f0351dda42f4");
1113
1114 // /*
1115 // * Checklist2
1116 // * - Campanula
1117 // * - Campanula persicifolia
1118 // * Checklist
1119 // * - Abies
1120 // * - Abies alba
1121 // * - Abieas alba subs. brota
1122 // * - Abies palma
1123 // * -Pinus
1124 // */
1125 // Classification checklist2 = Classification.NewInstance("Checklist2");
1126 // checklist2.setUuid(checklist2Uuid);
1127 //
1128 // IBotanicalName campanulaName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1129 // campanulaName.setGenusOrUninomial("Campanula");
1130 // Taxon campanula = Taxon.NewInstance(campanulaName, null);
1131 //
1132 // IBotanicalName campanulaPersicifoliaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1133 // campanulaPersicifoliaName.setGenusOrUninomial("Campanula");
1134 // campanulaPersicifoliaName.setSpecificEpithet("persicifolia");
1135 // Taxon campanulaPersicifolia = Taxon.NewInstance(campanulaPersicifoliaName, null);
1136 //
1137 // TaxonNode campanulaNode = checklist2.addChildTaxon(campanula, null, null);
1138 // campanulaNode.setUuid(campanulaNodeUuid);
1139 // TaxonNode campanulaPersicifoliaNode = checklist2.addParentChild(campanula, campanulaPersicifolia, null, null);
1140 // campanulaPersicifoliaNode.setUuid(campanulaPersicifoliaNodeUuid);
1141 //
1142 // Classification checklist = Classification.NewInstance("Checklist");
1143 // checklist.setUuid(classificationUuid);
1144 //
1145 // IBotanicalName abiesName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1146 // abiesName.setGenusOrUninomial("Abies");
1147 // Taxon abies = Taxon.NewInstance(abiesName, null);
1148 //
1149 // IBotanicalName abiesAlbaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1150 // abiesAlbaName.setGenusOrUninomial("Abies");
1151 // abiesAlbaName.setSpecificEpithet("alba");
1152 // Taxon abiesAlba = Taxon.NewInstance(abiesAlbaName, null);
1153 //
1154 // IBotanicalName abiesAlbaSubBrotaName = TaxonNameFactory.NewBotanicalInstance(Rank.SUBSPECIES());
1155 // abiesAlbaSubBrotaName.setGenusOrUninomial("Abies");
1156 // abiesAlbaSubBrotaName.setSpecificEpithet("alba");
1157 // abiesAlbaSubBrotaName.setInfraSpecificEpithet("brota");
1158 // Taxon abiesAlbaSubBrota = Taxon.NewInstance(abiesAlbaSubBrotaName, null);
1159 //
1160 // IBotanicalName abiesPalmaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1161 // abiesPalmaName.setGenusOrUninomial("Abies");
1162 // abiesPalmaName.setSpecificEpithet("palma");
1163 // Taxon abiesPalma = Taxon.NewInstance(abiesPalmaName, null);
1164 //
1165 // IBotanicalName pinusName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1166 // pinusName.setGenusOrUninomial("Pinus");
1167 // Taxon pinus = Taxon.NewInstance(pinusName, null);
1168 //
1169 // TaxonNode abiesNode = checklist.addChildTaxon(abies, null, null);
1170 // abiesNode.setUuid(abiesNodeUuid);
1171 // TaxonNode abiesAlbaNode = checklist.addParentChild(abies, abiesAlba, null, null);
1172 // abiesAlbaNode.setUuid(abiesAlbaNodeUuid);
1173 // TaxonNode abiesAlbaSubBrotaNode = checklist.addParentChild(abiesAlba, abiesAlbaSubBrota, null, null);
1174 // abiesAlbaSubBrotaNode.setUuid(abiesAlbaSubBrotaNodeUuid);
1175 // TaxonNode abiesPalmaNode = checklist.addParentChild(abies, abiesPalma, null, null);
1176 // abiesPalmaNode.setUuid(abiesPalmaNodeUuid);
1177 // TaxonNode pinusNode = checklist.addChildTaxon(pinus, null, null);
1178 // pinusNode.setUuid(pinusNodeUuid);
1179 //
1180 // taxonService.saveOrUpdate(campanula);
1181 // taxonService.saveOrUpdate(campanulaPersicifolia);
1182 // classificationService.saveOrUpdate(checklist2);
1183 //
1184 // taxonService.saveOrUpdate(abies);
1185 // taxonService.saveOrUpdate(abiesAlba);
1186 // taxonService.saveOrUpdate(abiesAlbaSubBrota);
1187 // taxonService.saveOrUpdate(abiesPalma);
1188 // taxonService.saveOrUpdate(pinus);
1189 // classificationService.saveOrUpdate(checklist);
1190 //
1191 //
1192 // setComplete();
1193 // endTransaction();
1194 //
1195 // String fileNameAppendix = "testFindCommonParentNode";
1196 //
1197 // writeDbUnitDataSetFile(new String[] {
1198 // "TAXONBASE", "TAXONNAME",
1199 // "TAXONRELATIONSHIP",
1200 // "HOMOTYPICALGROUP",
1201 // "CLASSIFICATION", "TAXONNODE",
1202 // "LANGUAGESTRING",
1203 // "HIBERNATE_SEQUENCES" // IMPORTANT!!!
1204 // },
1205 // fileNameAppendix );
1206
1207 Classification classification = classificationService.load(classificationUuid);
1208
1209 TaxonNode campanula = taxonNodeService.load(campanulaNodeUuid);
1210 TaxonNode campanulaPersicifolia = taxonNodeService.load(campanulaPersicifoliaNodeUuid);
1211 TaxonNode abies = taxonNodeService.load(abiesNodeUuid);
1212 TaxonNode abiesAlba = taxonNodeService.load(abiesAlbaNodeUuid);
1213 TaxonNode abiesPalma = taxonNodeService.load(abiesPalmaNodeUuid);
1214 TaxonNode pinus = taxonNodeService.load(pinusNodeUuid);
1215
1216 //check initial state
1217 assertTrue(campanula!=null);
1218 assertTrue(campanulaPersicifolia!=null);
1219 assertTrue(abies!=null);
1220 assertTrue(abiesAlba!=null);
1221 assertTrue(abiesPalma!=null);
1222 assertTrue(pinus!=null);
1223
1224 TaxonNodeDto classificationRootNodeDto = new TaxonNodeDto(classification.getRootNode());
1225 TaxonNodeDto campanulaDto = new TaxonNodeDto(campanula);
1226 TaxonNodeDto campanulaPersicifoliaDto = new TaxonNodeDto(campanulaPersicifolia);
1227 TaxonNodeDto abiesDto = new TaxonNodeDto(abies);
1228 TaxonNodeDto abiesAlbaDto = new TaxonNodeDto(abiesAlba);
1229 TaxonNodeDto abiesPalmaDto = new TaxonNodeDto(abiesPalma);
1230 TaxonNodeDto pinusDto = new TaxonNodeDto(pinus);
1231
1232 List<TaxonNodeDto> nodes = new ArrayList<>();
1233 nodes.add(campanulaDto);
1234 TaxonNodeDto commonParentNodeDto = taxonNodeService.findCommonParentDto(nodes);
1235 assertEquals(campanulaDto.getUuid(), commonParentNodeDto.getUuid());
1236
1237 nodes = new ArrayList<>();
1238 nodes.add(campanulaDto);
1239 nodes.add(campanulaPersicifoliaDto);
1240 commonParentNodeDto = taxonNodeService.findCommonParentDto(nodes);
1241 assertEquals(campanulaDto.getUuid(), commonParentNodeDto.getUuid());
1242
1243 nodes = new ArrayList<>();
1244 nodes.add(campanulaDto);
1245 nodes.add(abiesAlbaDto);
1246 commonParentNodeDto = taxonNodeService.findCommonParentDto(nodes);
1247 assertNull(commonParentNodeDto);
1248
1249 nodes = new ArrayList<>();
1250 nodes.add(abiesAlbaDto);
1251 nodes.add(abiesPalmaDto);
1252 commonParentNodeDto = taxonNodeService.findCommonParentDto(nodes);
1253 assertEquals(abiesDto.getUuid(), commonParentNodeDto.getUuid());
1254
1255 nodes = new ArrayList<>();
1256 nodes.add(abiesDto);
1257 nodes.add(pinusDto);
1258 commonParentNodeDto = taxonNodeService.findCommonParentDto(nodes);
1259 assertEquals(classificationRootNodeDto.getUuid(), commonParentNodeDto.getUuid());
1260 }
1261
1262 @Test //8127 //5536 //10101
1263 @Ignore // see #10101
1264 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="/eu/etaxonomy/cdm/database/ClearDBDataSet.xml")
1265 public final void testMergeDetached(){
1266
1267 //create classifications with 2 child nodes
1268 Classification tree = Classification.NewInstance("Classification");
1269 TaxonNode child1 = tree.getRootNode().addChildTaxon(Taxon.NewInstance(null, null), null);
1270 TaxonNode child2 = tree.getRootNode().addChildTaxon(null, null);
1271 classificationService.save(tree);
1272 taxonNodeService.save(child1);
1273 taxonNodeService.save(child2);
1274 commitAndStartNewTransaction();
1275
1276 //load root node and make it detached
1277 TaxonNode rootNode = taxonNodeService.find(tree.getRootNode().getUuid());
1278 rootNode.getChildNodes().get(0).getChildNodes().size(); //initialize children
1279 rootNode.getChildNodes().get(1).getChildNodes().size(); //initialize children
1280 commitAndStartNewTransaction(); //detach
1281
1282 //replace nodes and merge
1283 TaxonNode childToRemove = rootNode.getChildNodes().get(0);
1284 rootNode.deleteChildNode(childToRemove);
1285 TaxonNode child3 =rootNode.addChildTaxon(null, null);
1286 taxonNodeService.merge(rootNode, childToRemove);
1287 commitAndStartNewTransaction(tableNames);
1288
1289 //test result
1290 rootNode = taxonNodeService.find(tree.getRootNode().getUuid());
1291 rootNode.getChildNodes();
1292 Assert.assertEquals(2, rootNode.getChildNodes().size());
1293 Assert.assertEquals(child2.getUuid(), rootNode.getChildNodes().get(0).getUuid());
1294 Assert.assertEquals(child3.getUuid(), rootNode.getChildNodes().get(1).getUuid());
1295 Assert.assertEquals("Should be root + 2 children", 3, taxonNodeService.count(TaxonNode.class));
1296 commitAndStartNewTransaction();
1297
1298 // System.out.println("NEXT");
1299 //same with classification
1300 //load root node and make it detached
1301 Classification treeLoaded = classificationService.find(tree.getUuid());
1302 rootNode = treeLoaded.getRootNode();
1303 rootNode.getChildNodes().get(0); //initialize children
1304 commitAndStartNewTransaction(); //detach
1305
1306 //replace nodes and merge
1307 childToRemove = rootNode.getChildNodes().get(0);
1308 rootNode.deleteChildNode(childToRemove);
1309 TaxonNode child4 = rootNode.addChildTaxon(null, null);
1310
1311 @SuppressWarnings("unused")
1312 Classification mergedClassification = classificationService.merge(treeLoaded, childToRemove);
1313
1314 //NOTE: maybe interesting to know, that if not using orphan removal
1315 // resorting the index does not take place if not touching the children list somehow.
1316 // The sortindex starts than at some number > 0 and may contain nulls.
1317 // If touching the list like below the index starts at 0. This is now
1318 // automatically handled in PostMergeEntityListener.
1319 // mergedKey.getRoot().getChildren().size();
1320
1321 commitAndStartNewTransaction(tableNames);
1322
1323 rootNode = taxonNodeService.find(classification.getRootNode().getUuid());
1324 rootNode.getChildNodes();
1325 Assert.assertEquals(2, rootNode.getChildNodes().size());
1326 Assert.assertEquals(child3.getUuid(), rootNode.getChildNodes().get(0).getUuid());
1327 Assert.assertEquals(child4.getUuid(), rootNode.getChildNodes().get(1).getUuid());
1328 Assert.assertEquals("Should be root + 2 children", 3, taxonNodeService.count(TaxonNode.class));
1329 }
1330
1331 @Test //#10101
1332 @Ignore //see #10101
1333 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="/eu/etaxonomy/cdm/database/ClearDBDataSet.xml")
1334 public void testMergeDetachedWithMove() {
1335
1336 //create classification with 2 child nodes
1337 Classification tree = Classification.NewInstance("Classification");
1338 TaxonNode child1 = tree.getRootNode().addChildTaxon(null, null);
1339 TaxonNode child2 = tree.getRootNode().addChildTaxon(null, null);
1340 classificationService.save(tree);
1341 taxonNodeService.save(child1);
1342 taxonNodeService.save(child2);
1343 commitAndStartNewTransaction();
1344
1345 //load root node and make it detached
1346 Classification keyLoaded = classificationService.find(tree.getUuid());
1347 TaxonNode rootNode = keyLoaded.getRootNode();
1348 rootNode.getChildNodes().get(0).getChildNodes().size(); //initialize children
1349 rootNode.getChildNodes().get(1).getChildNodes().size(); //initialize children
1350 commitAndStartNewTransaction(); //detach
1351
1352 //replace nodes and merge
1353 TaxonNode childMove = rootNode.getChildNodes().get(0);
1354 TaxonNode newParentNode = rootNode.getChildNodes().get(1);
1355 TaxonNode child3 = newParentNode.addChildNode(childMove, null, null);
1356 TaxonNode child4 =rootNode.addChildTaxon(null, null);
1357 taxonNodeService.saveOrUpdate(child4);
1358
1359 @SuppressWarnings("unused")
1360 //no removed child to delete here
1361 Classification mergedTree = classificationService.merge(keyLoaded, new CdmBase[]{});
1362
1363 commitAndStartNewTransaction(tableNames);
1364
1365 rootNode = taxonNodeService.find(tree.getRootNode().getUuid());
1366 rootNode.getChildNodes();
1367 Assert.assertEquals(2, rootNode.getChildNodes().size());
1368 TaxonNode firstChild = rootNode.getChildNodes().get(0);
1369 Assert.assertEquals(child2.getUuid(), firstChild.getUuid());
1370 Assert.assertEquals(child4.getUuid(), rootNode.getChildNodes().get(1).getUuid());
1371 Assert.assertEquals(1, firstChild.getChildNodes().size());
1372 Assert.assertEquals(child1.getUuid(), firstChild.getChildNodes().get(0).getUuid());
1373 Assert.assertEquals("Should be root + 2 children + 1 grandchild", 4, taxonNodeService.count(TaxonNode.class));
1374 }
1375
1376 @Test //#10101
1377 @Ignore //see #10101
1378 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="/eu/etaxonomy/cdm/database/ClearDBDataSet.xml")
1379 public final void testSaveDetached(){
1380
1381 //create classifications with 2 child nodes
1382 Classification tree = Classification.NewInstance("Classification");
1383 TaxonNode child1 = tree.getRootNode().addChildTaxon(Taxon.NewInstance(null, null), null);
1384 TaxonNode child2 = tree.getRootNode().addChildTaxon(null, null);
1385 classificationService.save(tree);
1386 taxonNodeService.save(child1);
1387 taxonNodeService.save(child2);
1388 commitAndStartNewTransaction();
1389
1390 //load root node and make it detached
1391 TaxonNode rootNode = taxonNodeService.find(tree.getRootNode().getUuid());
1392 rootNode.getChildNodes().get(0).getChildNodes().size(); //initialize children
1393 rootNode.getChildNodes().get(1).getChildNodes().size(); //initialize children
1394 commitAndStartNewTransaction(); //detach
1395
1396 //replace nodes and merge
1397 TaxonNode childToRemove = rootNode.getChildNodes().get(0);
1398 rootNode.deleteChildNode(childToRemove);
1399 TaxonNode child3 =rootNode.addChildTaxon(null, null);
1400 taxonNodeService.saveOrUpdate(rootNode);
1401 taxonNodeService.delete(childToRemove.getUuid()); //combined method like in merge does not yet exist for saveOrUpdate
1402 commitAndStartNewTransaction(tableNames);
1403
1404 //test result
1405 rootNode = taxonNodeService.find(tree.getRootNode().getUuid());
1406 rootNode.getChildNodes();
1407 Assert.assertEquals(2, rootNode.getChildNodes().size());
1408 Assert.assertEquals(child2.getUuid(), rootNode.getChildNodes().get(0).getUuid());
1409 Assert.assertEquals(child3.getUuid(), rootNode.getChildNodes().get(1).getUuid());
1410 Assert.assertEquals("Should be root + 2 children", 3, taxonNodeService.count(TaxonNode.class));
1411 commitAndStartNewTransaction();
1412
1413 // System.out.println("NEXT");
1414 //same with classification
1415 //load root node and make it detached
1416 Classification treeLoaded = classificationService.find(tree.getUuid());
1417 rootNode = treeLoaded.getRootNode();
1418 rootNode.getChildNodes().get(0); //initialize children
1419 commitAndStartNewTransaction(); //detach
1420
1421 //replace nodes and merge
1422 childToRemove = rootNode.getChildNodes().get(0);
1423 rootNode.deleteChildNode(childToRemove);
1424 TaxonNode child4 = rootNode.addChildTaxon(null, null);
1425
1426 //TODO can't work yet as TaxonNodes are not cascaded on purpose
1427 classificationService.saveOrUpdate(treeLoaded);
1428 taxonNodeService.delete(childToRemove.getUuid());
1429
1430 commitAndStartNewTransaction(tableNames);
1431
1432 rootNode = taxonNodeService.find(classification.getRootNode().getUuid());
1433 rootNode.getChildNodes();
1434 Assert.assertEquals(2, rootNode.getChildNodes().size());
1435 Assert.assertEquals(child3.getUuid(), rootNode.getChildNodes().get(0).getUuid());
1436 Assert.assertEquals(child4.getUuid(), rootNode.getChildNodes().get(1).getUuid());
1437 Assert.assertEquals("Should be root + 2 children", 3, taxonNodeService.count(TaxonNode.class));
1438
1439 //TODO implement testSaveDetachedWithMove like in TermNode and PolytomousKeyNode service tests
1440 }
1441
1442 @Test
1443 @DataSet("ClassificationServiceImplTest.xml")
1444 public final void testCloneClassification(){
1445
1446 Classification originalClassification = classificationDao.load(ClassificationServiceImplTest.CLASSIFICATION_UUID);
1447
1448 SubtreeCloneConfigurator config = SubtreeCloneConfigurator.NewBaseInstance(
1449 originalClassification.getRootNode().getUuid(), "Cloned classification");
1450
1451 Classification classificationClone = (Classification) taxonNodeService.cloneSubtree(config).getCdmEntity();
1452
1453 assertEquals("# of direct children does not match", originalClassification.getChildNodes().size(), classificationClone.getChildNodes().size());
1454 assertEquals("# of all nodes does not match", originalClassification.getAllNodes().size(), classificationClone.getAllNodes().size());
1455
1456 Set<UUID> originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
1457 for (TaxonNode clonedTaxonNode : classificationClone.getChildNodes()) {
1458 //test no reuse of taxon
1459 Taxon clonedTaxon = clonedTaxonNode.getTaxon();
1460 TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
1461 assertNull(originalNode);
1462
1463 //check relationship
1464 assertEquals(0, clonedTaxon.getRelationsFromThisTaxon().size());
1465
1466 //test taxon sec
1467 assertTrue(originalTaxonSecUuids.contains(clonedTaxon.getSec().getUuid()));
1468 }
1469 commitAndStartNewTransaction();
1470
1471 //test reuse taxon
1472 config.setReuseTaxa(true);
1473 classificationClone = (Classification) taxonNodeService.cloneSubtree(config).getCdmEntity();
1474 assertEquals("# of direct children does not match", originalClassification.getChildNodes().size(), classificationClone.getChildNodes().size());
1475 originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
1476 for (TaxonNode taxonNode : classificationClone.getChildNodes()) {
1477 //test no reuse of taxon
1478 Taxon clonedTaxon = taxonNode.getTaxon();
1479 TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
1480 assertNotNull(originalNode);
1481 Taxon originalTaxon = originalNode.getTaxon();
1482 assertNotNull(originalTaxon);
1483
1484 //check relationship
1485 assertEquals(0, clonedTaxon.getRelationsFromThisTaxon().size());
1486
1487 //test taxon sec
1488 assertEquals(originalTaxon.getSec().getUuid(), clonedTaxon.getSec().getUuid());
1489 }
1490 commitAndStartNewTransaction();
1491
1492 config.setReuseTaxa(false); //reset
1493 config.setRelationTypeToOldTaxon(TaxonRelationshipType.CONGRUENT_TO());
1494 Reference sec = referenceDao.findByUuid(UUID.fromString("719d136b-409e-40d0-9561-46f6999465b4"));
1495 config.setTaxonSecundumUuid(sec.getUuid());
1496 classificationClone = (Classification) taxonNodeService.cloneSubtree(config).getCdmEntity();
1497 originalTaxonSecUuids = originalClassification.getAllNodes().stream().map(tn -> tn.getTaxon().getSec().getUuid()).collect(Collectors.toSet());
1498 for (TaxonNode taxonNode : classificationClone.getChildNodes()) {
1499 //test no reuse of taxon
1500 Taxon clonedTaxon = taxonNode.getTaxon();
1501 TaxonNode originalNode = originalClassification.getNode(clonedTaxon);
1502 assertNull(originalNode);
1503
1504 //check relationship
1505 TaxonRelationship relShip = clonedTaxon.getRelationsFromThisTaxon().iterator().next();
1506 Taxon relatedTaxon = relShip.getToTaxon();
1507 Taxon relatedOriginalTaxon = originalClassification.getNode(relatedTaxon).getTaxon();
1508 assertEquals(relatedOriginalTaxon.getName(), clonedTaxon.getName());
1509 assertTrue(relShip.getType().equals(TaxonRelationshipType.CONGRUENT_TO()));
1510
1511 //test taxon sec
1512 assertEquals(relatedOriginalTaxon.getSec().getUuid(), clonedTaxon.getSec().getUuid());
1513 }
1514 commitAndStartNewTransaction();
1515
1516 //no recursive for root
1517 config = SubtreeCloneConfigurator.NewBaseInstance(
1518 originalClassification.getRootNode().getUuid(), "Cloned classification");
1519 config.setDoRecursive(false);
1520 classificationClone = (Classification) taxonNodeService.cloneSubtree(config).getCdmEntity();
1521 Assert.assertTrue(classificationClone.getRootNode().getChildNodes().isEmpty());
1522
1523 //no recursive for root
1524 config = SubtreeCloneConfigurator.NewBaseInstance(
1525 UUID.fromString("26cc5c08-72df-45d4-84ea-ce81e7e53114"), "Cloned classification");
1526 config.setDoRecursive(false);
1527 classificationClone = (Classification) taxonNodeService.cloneSubtree(config).getCdmEntity();
1528 List<TaxonNode> nodes = classificationClone.getRootNode().getChildNodes();
1529 Assert.assertEquals(1, nodes.size());
1530 Taxon clonedTaxon = nodes.iterator().next().getTaxon();
1531 Assert.assertEquals("Name should be the same as for the original taxon", UUID.fromString("301e2bf0-85a4-442a-93f6-63d3b9ee8c3d"), clonedTaxon.getName().getUuid());
1532 Assert.assertTrue(nodes.iterator().next().getChildNodes().isEmpty());
1533 }
1534
1535 @Override
1536 // @Test
1537 public void createTestDataSet() throws FileNotFoundException {
1538 UUID checklist2Uuid = UUID.fromString("c6e3a598-3b6c-4ef5-8b01-5bdb3de5a9fd");
1539 UUID campanulaNodeUuid = UUID.fromString("62fa918d-a1d8-4284-ae4b-93478bde8656");
1540 UUID campanulaPersicifoliaNodeUuid = UUID.fromString("dce3defa-5123-44a7-8008-0cc9b27461f6");
1541
1542 UUID classificationUuid = UUID.fromString("029b4c07-5903-4dcf-87e8-406ed0e0285f");
1543 UUID abiesNodeUuid = UUID.fromString("f8306fd3-9825-41bf-94aa-a7b5790b553e");
1544 UUID abiesAlbaNodeUuid = UUID.fromString("c70f76e5-2dcb-41c5-ae6f-d756e0a0fae0");
1545 UUID abiesAlbaSubBrotaNodeUuid = UUID.fromString("06d58161-7707-44b5-b720-6c0eb916b37c");
1546 UUID abiesPalmaNodeUuid = UUID.fromString("6dfd30dd-e589-493a-b66a-19c4cb374f92");
1547
1548 UUID pinusNodeUuid = UUID.fromString("5d8e8341-f5e9-4616-96cf-f0351dda42f4");
1549
1550 /*
1551 * Checklist2
1552 * - Campanula
1553 * - Campanula persicifolia
1554 * Checklist
1555 * - Abies
1556 * - Abies alba
1557 * - Abieas alba subs. brota
1558 * - Abies palma
1559 * -Pinus
1560 */
1561 Classification checklist2 = Classification.NewInstance("Checklist2");
1562 checklist2.setUuid(checklist2Uuid);
1563
1564 IBotanicalName campanulaName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1565 campanulaName.setGenusOrUninomial("Campanula");
1566 Taxon campanula = Taxon.NewInstance(campanulaName, null);
1567
1568 IBotanicalName campanulaPersicifoliaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1569 campanulaPersicifoliaName.setGenusOrUninomial("Campanula");
1570 campanulaPersicifoliaName.setSpecificEpithet("persicifolia");
1571 Taxon campanulaPersicifolia = Taxon.NewInstance(campanulaPersicifoliaName, null);
1572
1573 TaxonNode campanulaNode = checklist2.addChildTaxon(campanula, null, null);
1574 campanulaNode.setUuid(campanulaNodeUuid);
1575 TaxonNode campanulaPersicifoliaNode = checklist2.addParentChild(campanula, campanulaPersicifolia, null, null);
1576 campanulaPersicifoliaNode.setUuid(campanulaPersicifoliaNodeUuid);
1577
1578 Classification checklist = Classification.NewInstance("Checklist");
1579 checklist.setUuid(classificationUuid);
1580
1581 IBotanicalName abiesName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1582 abiesName.setGenusOrUninomial("Abies");
1583 Taxon abies = Taxon.NewInstance(abiesName, null);
1584
1585 IBotanicalName abiesAlbaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1586 abiesAlbaName.setGenusOrUninomial("Abies");
1587 abiesAlbaName.setSpecificEpithet("alba");
1588 Taxon abiesAlba = Taxon.NewInstance(abiesAlbaName, null);
1589
1590 IBotanicalName abiesAlbaSubBrotaName = TaxonNameFactory.NewBotanicalInstance(Rank.SUBSPECIES());
1591 abiesAlbaSubBrotaName.setGenusOrUninomial("Abies");
1592 abiesAlbaSubBrotaName.setSpecificEpithet("alba");
1593 abiesAlbaSubBrotaName.setInfraSpecificEpithet("brota");
1594 Taxon abiesAlbaSubBrota = Taxon.NewInstance(abiesAlbaSubBrotaName, null);
1595
1596 IBotanicalName abiesPalmaName = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
1597 abiesPalmaName.setGenusOrUninomial("Abies");
1598 abiesPalmaName.setSpecificEpithet("palma");
1599 Taxon abiesPalma = Taxon.NewInstance(abiesPalmaName, null);
1600
1601 IBotanicalName pinusName = TaxonNameFactory.NewBotanicalInstance(Rank.GENUS());
1602 pinusName.setGenusOrUninomial("Pinus");
1603 Taxon pinus = Taxon.NewInstance(pinusName, null);
1604
1605 TaxonNode abiesNode = checklist.addChildTaxon(abies, null, null);
1606 abiesNode.setUuid(abiesNodeUuid);
1607 TaxonNode abiesAlbaNode = checklist.addParentChild(abies, abiesAlba, null, null);
1608 abiesAlbaNode.setUuid(abiesAlbaNodeUuid);
1609 TaxonNode abiesAlbaSubBrotaNode = checklist.addParentChild(abiesAlba, abiesAlbaSubBrota, null, null);
1610 abiesAlbaSubBrotaNode.setUuid(abiesAlbaSubBrotaNodeUuid);
1611 TaxonNode abiesPalmaNode = checklist.addParentChild(abies, abiesPalma, null, null);
1612 abiesPalmaNode.setUuid(abiesPalmaNodeUuid);
1613 TaxonNode pinusNode = checklist.addChildTaxon(pinus, null, null);
1614 pinusNode.setUuid(pinusNodeUuid);
1615
1616 taxonService.saveOrUpdate(campanula);
1617 taxonService.saveOrUpdate(campanulaPersicifolia);
1618 classificationService.saveOrUpdate(checklist2);
1619
1620 taxonService.saveOrUpdate(abies);
1621 taxonService.saveOrUpdate(abiesAlba);
1622 taxonService.saveOrUpdate(abiesAlbaSubBrota);
1623 taxonService.saveOrUpdate(abiesPalma);
1624 taxonService.saveOrUpdate(pinus);
1625 classificationService.saveOrUpdate(checklist);
1626
1627 setComplete();
1628 endTransaction();
1629
1630 String fileNameAppendix = "testFindCommonParentNode";
1631
1632 writeDbUnitDataSetFile(new String[] {
1633 "TAXONBASE", "TAXONNAME",
1634 "TAXONRELATIONSHIP",
1635 "HOMOTYPICALGROUP",
1636 "CLASSIFICATION", "TAXONNODE",
1637 "LANGUAGESTRING",
1638 "HIBERNATE_SEQUENCES" // IMPORTANT!!!
1639 },
1640 fileNameAppendix, true );
1641 }
1642 }