3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.cdm
.strategy
.merge
;
13 import java
.util
.HashSet
;
15 import java
.util
.UUID
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.joda
.time
.DateTime
;
19 import org
.junit
.After
;
20 import org
.junit
.AfterClass
;
21 import org
.junit
.Assert
;
22 import org
.junit
.Before
;
23 import org
.junit
.BeforeClass
;
24 import org
.junit
.Ignore
;
25 import org
.junit
.Test
;
27 import eu
.etaxonomy
.cdm
.model
.agent
.Address
;
28 import eu
.etaxonomy
.cdm
.model
.agent
.Contact
;
29 import eu
.etaxonomy
.cdm
.model
.agent
.Institution
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.InstitutionalMembership
;
31 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
32 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
33 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
34 import eu
.etaxonomy
.cdm
.model
.common
.DefaultTermInitializer
;
35 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
36 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
37 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
38 import eu
.etaxonomy
.cdm
.model
.location
.Point
;
39 import eu
.etaxonomy
.cdm
.model
.location
.ReferenceSystem
;
40 import eu
.etaxonomy
.cdm
.model
.location
.WaterbodyOrCountry
;
41 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
42 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
43 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationshipType
;
44 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
45 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignationStatus
;
46 import eu
.etaxonomy
.cdm
.model
.occurrence
.Specimen
;
47 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
48 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
49 //import eu.etaxonomy.cdm.model.reference.PrintSeries;
50 //import eu.etaxonomy.cdm.model.reference.Thesis;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
53 import eu
.etaxonomy
.cdm
.strategy
.cache
.reference
.INomenclaturalReferenceCacheStrategy
;
60 public class DefaultMergeStrategyTest
{
61 @SuppressWarnings("unused")
62 private static final Logger logger
= Logger
.getLogger(DefaultMergeStrategyTest
.class);
64 private DefaultMergeStrategy bookMergeStrategy
;
65 private Reference book1
;
66 private String editionString1
="Ed.1";
67 private String volumeString1
="Vol.1";
69 private Reference printSeries1
;
70 private Annotation annotation1
;
71 private String title1
= "Title1";
72 private TimePeriod datePublished1
= TimePeriod
.NewInstance(2000);
73 private int hasProblem1
= 1;
76 private Reference book2
;
77 private String editionString2
="Ed.2";
78 private String volumeString2
="Vol.2";
80 private Reference printSeries2
;
81 private Annotation annotation2
;
82 private String annotationString2
;
83 private String title2
= "Title2";
84 private DateTime created2
= new DateTime(1999, 3, 1, 0, 0, 0, 0);
85 private TimePeriod datePublished2
= TimePeriod
.NewInstance(2002);
86 private int hasProblem2
= 1;
88 private ReferenceFactory refFactory
;
91 private Reference book3
;
94 * @throws java.lang.Exception
97 public static void setUpBeforeClass() throws Exception
{
98 DefaultTermInitializer termInitializer
= new DefaultTermInitializer();
99 termInitializer
.initialize();
103 * @throws java.lang.Exception
106 public static void tearDownAfterClass() throws Exception
{
110 * @throws java.lang.Exception
113 public void setUp() throws Exception
{
114 refFactory
= ReferenceFactory
.newInstance();
115 bookMergeStrategy
= DefaultMergeStrategy
.NewInstance(Reference
.class);
116 team1
= Team
.NewInstance();
117 team1
.setTitleCache("Team1", true);
118 team2
= Team
.NewInstance();
119 team2
.setTitleCache("Team2", true);
120 printSeries1
= refFactory
.newPrintSeries("Series1");
121 printSeries2
= refFactory
.newPrintSeries("Series2");
122 annotation1
= Annotation
.NewInstance("Annotation1", null);
123 annotationString2
= "Annotation2";
124 annotation2
= Annotation
.NewInstance(annotationString2
, null);
126 book1
= refFactory
.newBook();
127 book1
.setAuthorTeam(team1
);
128 book1
.setTitle(title1
);
129 book1
.setEdition(editionString1
);
130 book1
.setVolume(volumeString1
);
131 book1
.setInReference(printSeries1
);
132 book1
.addAnnotation(annotation1
);
133 book1
.setDatePublished(datePublished1
);
134 book1
.setParsingProblem(hasProblem1
);
135 lsid1
= new LSID("authority1", "namespace1", "object1", "revision1");
136 book1
.setLsid(lsid1
);
137 book1
.setNomenclaturallyRelevant(false);
139 book2
= refFactory
.newBook();
140 book2
.setAuthorTeam(team2
);
141 book2
.setTitle(title2
);
142 book2
.setEdition(editionString2
);
143 book2
.setVolume(volumeString2
);
144 book2
.setInReference(printSeries2
);
145 book2
.addAnnotation(annotation2
);
146 book2
.setCreated(created2
);
147 book2
.setDatePublished(datePublished2
);
148 book2
.setParsingProblem(hasProblem2
);
149 lsid2
= new LSID("authority2", "namespace2", "object2", "revision2");
150 book2
.setLsid(lsid2
);
151 book2
.setNomenclaturallyRelevant(true);
156 * @throws java.lang.Exception
159 public void tearDown() throws Exception
{
162 //********************* TEST *********************************************/
165 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#NewInstance(java.lang.Class)}.
168 public void testNewInstance() {
169 Assert
.assertNotNull(bookMergeStrategy
);
170 Assert
.assertEquals(Reference
.class, bookMergeStrategy
.getMergeClass());
174 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
177 public void testGetMergeMode() {
178 Assert
.assertEquals("Merge mode for title should be MergeMode.FIRST", MergeMode
.FIRST
, bookMergeStrategy
.getMergeMode("title"));
182 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
185 public void testGetSetMergeMode() {
188 bookMergeStrategy
.setMergeMode("edition", MergeMode
.SECOND
);
189 Assert
.assertEquals("Merge mode for edition should be", MergeMode
.SECOND
, bookMergeStrategy
.getMergeMode("edition"));
190 } catch (MergeException e1
) {
195 bookMergeStrategy
.setMergeMode("xxx", MergeMode
.SECOND
);
196 Assert
.fail("A property name must exist, otherwise an exception must be thrown");
197 } catch (Exception e
) {
202 bookMergeStrategy
.setMergeMode("cacheStrategy", MergeMode
.SECOND
);
203 Assert
.fail("CacheStrategy is transient and therefore not a legal merge parameter");
204 } catch (Exception e
) {
209 bookMergeStrategy
.setMergeMode("id", MergeMode
.SECOND
);
210 Assert
.fail("Identifier merge mode must always be MergeMode.FIRST");
211 } catch (Exception e
) {
216 bookMergeStrategy
.setMergeMode("uuid", MergeMode
.SECOND
);
217 Assert
.fail("Identifier merge mode must always be MergeMode.FIRST");
218 } catch (Exception e
) {
227 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
228 * @throws MergeException
231 public void testInvokeReferences() throws MergeException
{
232 INomenclaturalReferenceCacheStrategy
<Reference
> cacheStrategy1
= (INomenclaturalReferenceCacheStrategy
<Reference
>)book1
.getCacheStrategy();
233 int id
= book1
.getId();
234 UUID uuid
= book1
.getUuid();
236 bookMergeStrategy
.setMergeMode("edition", MergeMode
.SECOND
);
237 bookMergeStrategy
.setMergeMode("volume", MergeMode
.NULL
);
238 bookMergeStrategy
.setMergeMode("authorTeam", MergeMode
.SECOND
);
239 bookMergeStrategy
.setMergeMode("created", MergeMode
.SECOND
);
240 bookMergeStrategy
.setMergeMode("updated",MergeMode
.NULL
);
241 bookMergeStrategy
.setMergeMode("datePublished", MergeMode
.SECOND
);
242 bookMergeStrategy
.setMergeMode("parsingProblem", MergeMode
.SECOND
);
243 bookMergeStrategy
.setMergeMode("inReference", MergeMode
.SECOND
);
244 bookMergeStrategy
.setMergeMode("lsid", MergeMode
.SECOND
);
246 bookMergeStrategy
.invoke(book1
, book2
);
247 } catch (MergeException e
) {
249 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
251 Assert
.assertEquals("Title should stay the same", title1
, book1
.getTitle());
252 Assert
.assertEquals("Edition should become edition 2", editionString2
, book1
.getEdition());
253 Assert
.assertNull("Volume should be null", book1
.getVolume());
256 Assert
.assertEquals("Has problem must be hasProblem2", hasProblem2
, book1
.getParsingProblem());
257 Assert
.assertEquals("nomenclaturally relevant must have value true (AND semantics)", true, book1
.isNomenclaturallyRelevant() );
261 Assert
.assertSame("AuthorTeam must be the one of book2", team2
, book1
.getAuthorTeam());
262 Assert
.assertSame("In Series must be the one of book2", printSeries2
, book1
.getInReference());
265 Assert
.assertSame("Cache strategy is transient and shouldn't change therefore", cacheStrategy1
, book1
.getCacheStrategy());
269 Assert
.assertSame("Created must be created2", created2
, book1
.getCreated());
270 //TODO updated should have the actual date if any value has changed
271 Assert
.assertSame("Created must be created2", null, book1
.getUpdated());
272 Assert
.assertSame("Created must be datePublsihed2", datePublished2
, book1
.getDatePublished());
273 //TODO this may not be correct
274 Assert
.assertSame("LSID must be LSID2", lsid2
, book1
.getLsid());
278 // book1.setProblemEnds(end);
279 // book1.setProtectedTitleCache(protectedTitleCache);
281 //annotations -> ADD_CLONE
282 Assert
.assertEquals("Annotations should contain annotations of both books", 2, book1
.getAnnotations().size());
283 boolean cloneExists
= false;
284 for (Annotation annotation
: book1
.getAnnotations()){
285 if (annotation
== this.annotation2
){
286 //Hibernate will not persist the exact same object. Probably this is a bug (the according row in the
287 //M:M table is not deleted and a unique constraints does not allow adding 2 rows with the same annotation_id
288 //This test can be changed once this bug does not exist anymore
289 Assert
.fail("Book1 should contain a clone of annotation2 but contains annotation2 itself");
290 }else if (annotationString2
.equals(annotation
.getText())){
294 Assert
.assertTrue("Book1 should contain a clone of annotation2", cloneExists
);
295 // Assert.assertEquals("Annotations from book2 should be deleted", 0, book2.getAnnotations().size());
298 Assert
.assertSame("Identifier must never be changed", id
, book1
.getId());
299 Assert
.assertSame("Identifier must never be changed", uuid
, book1
.getUuid());
302 Institution school1
= Institution
.NewInstance();
303 Institution school2
= Institution
.NewInstance();
305 Reference thesis1
= refFactory
.newThesis();
306 thesis1
.setSchool(school1
);
307 //Thesis thesis1 = Thesis.NewInstance(school1);
308 Reference thesis2
= refFactory
.newThesis();
309 thesis2
.setSchool(school2
);
310 DefaultMergeStrategy thesisStrategy
= DefaultMergeStrategy
.NewInstance(Reference
.class);
312 thesisStrategy
.setMergeMode("school", MergeMode
.SECOND
);
313 thesisStrategy
.invoke(thesis1
, thesis2
);
314 Assert
.assertSame("school must be school2", school2
, thesis1
.getSchool());
319 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
320 * @throws MergeException
324 public void testInvokeTxonNames() throws MergeException
{
325 IMergeStrategy botNameMergeStrategy
= DefaultMergeStrategy
.NewInstance(BotanicalName
.class);
326 BotanicalName botName1
= BotanicalName
.NewInstance(Rank
.SPECIES());
327 BotanicalName botName2
= BotanicalName
.NewInstance(Rank
.SPECIES());
328 BotanicalName botName3
= BotanicalName
.NewInstance(Rank
.SPECIES());
330 botName1
.setGenusOrUninomial("Genus1");
331 botName1
.setSpecificEpithet("species1");
332 botName1
.setAnamorphic(true);
334 botName2
.setGenusOrUninomial("Genus2");
335 botName2
.setSpecificEpithet("species2");
336 botName2
.setAnamorphic(false);
339 botName2
.addBasionym(botName3
, book1
, "p.22", null);
340 Specimen specimen1
= Specimen
.NewInstance();
341 botName2
.addSpecimenTypeDesignation(specimen1
, SpecimenTypeDesignationStatus
.HOLOTYPE(), book2
, "p.56", "originalNameString", false, true);
344 TaxonNameDescription description1
= TaxonNameDescription
.NewInstance();
345 botName1
.addDescription(description1
);
346 TaxonNameDescription description2
= TaxonNameDescription
.NewInstance();
347 botName1
.addDescription(description2
);
350 Team team1
= Team
.NewInstance();
351 Team team2
= Team
.NewInstance();
352 Person person1
= Person
.NewInstance();
353 botName1
.setCombinationAuthorTeam(team1
);
354 botName2
.setCombinationAuthorTeam(team2
);
357 TaxonBase taxon1
= Taxon
.NewInstance(botName1
, book1
);
358 TaxonBase taxon2
= Taxon
.NewInstance(botName2
, book2
);
361 botNameMergeStrategy
.setMergeMode("combinationAuthorTeam", MergeMode
.SECOND
);
362 botNameMergeStrategy
.setMergeMode("anamorphic", MergeMode
.AND
);
364 // botNameMergeStrategy.invoke(botName1, botName2);
365 } catch (MergeException e
) {
367 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
371 Assert
.assertEquals("Is anamorphic must be false", true && false, botName2
.isAnamorphic());
374 Set
<NameRelationship
> toRelations
= botName2
.getRelationsToThisName();
375 Set
<NameRelationship
> basionymRelations
= new HashSet
<NameRelationship
>();
376 for (NameRelationship toRelation
: toRelations
){
377 if (toRelation
.getType().equals(NameRelationshipType
.BASIONYM())){
378 basionymRelations
.add(toRelation
);
381 Assert
.assertEquals("Number of basionyms must be 1", 1, basionymRelations
.size());
382 Assert
.assertEquals("Basionym must have same reference", book1
, basionymRelations
.iterator().next().getCitation());
383 //TODO merge relation if matches() = true
386 Assert
.assertEquals("Number of specimen type designations must be 1", 1, botName2
.getSpecimenTypeDesignations().size());
387 //TODO add to all names etc.
390 Assert
.assertEquals("Number of descriptions must be 2", 2, botName1
.getDescriptions().size());
393 Assert
.assertEquals("Combination author must be combination author 1", team1
, botName1
.getCombinationAuthorTeam());
396 Assert
.assertEquals("TaxonName of taxon1 must be name1", botName1
, taxon1
.getName());
397 Assert
.assertEquals("TaxonName of taxon2 must be name2", botName2
, taxon2
.getName());
402 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
403 * @throws MergeException
406 public void testInvokeAgents() throws MergeException
{
407 IMergeStrategy teamMergeStrategy
= DefaultMergeStrategy
.NewInstance(Team
.class);
409 Team team1
= Team
.NewInstance();
410 Team team2
= Team
.NewInstance();
411 Team team3
= Team
.NewInstance();
413 Person person1
= Person
.NewTitledInstance("person1");
414 Person person2
= Person
.NewTitledInstance("person2");
415 Person person3
= Person
.NewTitledInstance("person3");
417 team1
.setTitleCache("Team1", true);
418 team1
.setNomenclaturalTitle("T.1");
419 String street1
= "Strasse1";
420 team1
.setContact(Contact
.NewInstance(street1
, "12345", "Berlin", WaterbodyOrCountry
.ARGENTINAARGENTINEREPUBLIC(),"pobox" , "Region", "a@b.de", "f12345", "+49-30-123456", "www.abc.de", Point
.NewInstance(2.4, 3.2, ReferenceSystem
.WGS84(), 3)));
421 team2
.setContact(Contact
.NewInstance("Street2", null, "London", null, null, null, null, "874599873", null, null, null));
422 String street3
= "Street3";
423 team2
.addAddress(street3
, null, null, null, null, null, Point
.NewInstance(1.1, 2.2, null, 4));
424 String emailAddress1
= "Email1";
425 team1
.addEmailAddress(emailAddress1
);
427 team2
.addTeamMember(person1
);
428 team2
.addTeamMember(person2
);
429 String emailAddress2
= "Email2";
430 team2
.addEmailAddress(emailAddress2
);
432 team3
.addTeamMember(person3
);
433 team3
.addEmailAddress("emailAddress3");
435 teamMergeStrategy
.invoke(team2
, team3
);
437 Assert
.assertEquals("Team2 must have 3 persons as members",3, team2
.getTeamMembers().size());
438 Assert
.assertTrue("Team2 must have person3 as new member", team2
.getTeamMembers().contains(person3
));
439 Assert
.assertSame("Team2 must have person3 as third member",person3
, team2
.getTeamMembers().get(2));
442 teamMergeStrategy
.invoke(team2
, team1
);
443 Contact team2Contact
= team2
.getContact();
444 Assert
.assertNotNull("team2Contact must not be null", team2Contact
);
445 Assert
.assertNotNull("Addresses must not be null", team2Contact
.getAddresses());
446 Assert
.assertEquals("Number of addresses must be 3", 3, team2Contact
.getAddresses().size());
447 Assert
.assertEquals("Number of email addresses must be 4", 4, team2Contact
.getEmailAddresses().size());
449 boolean street1Exists
= false;
450 boolean street3Exists
= false;
451 boolean country1Exists
= false;
452 for (Address address
: team2Contact
.getAddresses()){
453 if (street1
.equals(address
.getStreet())){
454 street1Exists
= true;
456 if (street3
.equals(address
.getStreet())){
457 street3Exists
= true;
459 if (WaterbodyOrCountry
.ARGENTINAARGENTINEREPUBLIC() == address
.getCountry()){
460 country1Exists
= true;
463 Assert
.assertTrue("Street1 must be one of the streets in team2's addresses", street1Exists
);
464 Assert
.assertTrue("Street3 must be one of the streets in team2's addressesss", street3Exists
);
465 Assert
.assertTrue("Argentina must be one of the countries in team2's addresses", country1Exists
);
468 Institution institution1
= Institution
.NewInstance();
469 institution1
.setTitleCache("inst1", true);
470 Institution institution2
= Institution
.NewInstance();
471 institution2
.setTitleCache("inst2", true);
473 TimePeriod period1
= TimePeriod
.NewInstance(2002, 2004);
474 TimePeriod period2
= TimePeriod
.NewInstance(2004, 2006);
476 person1
.addInstitutionalMembership(institution1
, period1
, "departement1", "role1");
477 person2
.addInstitutionalMembership(institution2
, period2
, "departement2", "role2");
479 IMergeStrategy personMergeStrategy
= DefaultMergeStrategy
.NewInstance(Person
.class);
480 personMergeStrategy
.invoke(person1
, person2
);
482 Assert
.assertEquals("Number of institutional memberships must be 2", 2, person1
.getInstitutionalMemberships().size());
483 for (InstitutionalMembership institutionalMembership
: person1
.getInstitutionalMemberships()){
484 Assert
.assertSame("Person of institutional memebership must be person1", person1
, institutionalMembership
.getPerson());