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
.Keyword
;
36 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
37 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
38 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
39 import eu
.etaxonomy
.cdm
.model
.location
.Point
;
40 import eu
.etaxonomy
.cdm
.model
.location
.ReferenceSystem
;
41 import eu
.etaxonomy
.cdm
.model
.location
.WaterbodyOrCountry
;
42 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
43 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
44 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationshipType
;
45 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
46 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignationStatus
;
47 import eu
.etaxonomy
.cdm
.model
.occurrence
.Specimen
;
48 import eu
.etaxonomy
.cdm
.model
.reference
.Book
;
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
;
66 private String editionString1
="Ed.1";
67 private String volumeString1
="Vol.1";
69 private PrintSeries printSeries1
;
70 private Annotation annotation1
;
71 private String title1
= "Title1";
72 private TimePeriod datePublished1
= TimePeriod
.NewInstance(2000);
73 private int hasProblem1
= 1;
77 private String editionString2
="Ed.2";
78 private String volumeString2
="Vol.2";
80 private PrintSeries 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;
93 * @throws java.lang.Exception
96 public static void setUpBeforeClass() throws Exception
{
97 DefaultTermInitializer termInitializer
= new DefaultTermInitializer();
98 termInitializer
.initialize();
102 * @throws java.lang.Exception
105 public static void tearDownAfterClass() throws Exception
{
109 * @throws java.lang.Exception
112 public void setUp() throws Exception
{
113 bookMergeStrategy
= DefaultMergeStrategy
.NewInstance(Book
.class);
114 team1
= Team
.NewInstance();
115 team1
.setTitleCache("Team1");
116 team2
= Team
.NewInstance();
117 team2
.setTitleCache("Team2");
118 printSeries1
= PrintSeries
.NewInstance("Series1");
119 printSeries2
= PrintSeries
.NewInstance("Series2");
120 annotation1
= Annotation
.NewInstance("Annotation1", null);
121 annotationString2
= "Annotation2";
122 annotation2
= Annotation
.NewInstance(annotationString2
, null);
124 book1
= Book
.NewInstance();
125 book1
.setAuthorTeam(team1
);
126 book1
.setTitle(title1
);
127 book1
.setEdition(editionString1
);
128 book1
.setVolume(volumeString1
);
129 book1
.setInSeries(printSeries1
);
130 book1
.addAnnotation(annotation1
);
131 book1
.setDatePublished(datePublished1
);
132 book1
.setParsingProblem(hasProblem1
);
133 lsid1
= new LSID("authority1", "namespace1", "object1", "revision1");
134 book1
.setLsid(lsid1
);
135 book1
.setNomenclaturallyRelevant(false);
137 book2
= Book
.NewInstance();
138 book2
.setAuthorTeam(team2
);
139 book2
.setTitle(title2
);
140 book2
.setEdition(editionString2
);
141 book2
.setVolume(volumeString2
);
142 book2
.setInSeries(printSeries2
);
143 book2
.addAnnotation(annotation2
);
144 book2
.setCreated(created2
);
145 book2
.setDatePublished(datePublished2
);
146 book2
.setParsingProblem(hasProblem2
);
147 lsid2
= new LSID("authority2", "namespace2", "object2", "revision2");
148 book2
.setLsid(lsid2
);
149 book2
.setNomenclaturallyRelevant(true);
154 * @throws java.lang.Exception
157 public void tearDown() throws Exception
{
160 //********************* TEST *********************************************/
163 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#NewInstance(java.lang.Class)}.
166 public void testNewInstance() {
167 Assert
.assertNotNull(bookMergeStrategy
);
168 Assert
.assertEquals(Book
.class, bookMergeStrategy
.getMergeClass());
172 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
175 public void testGetMergeMode() {
176 Assert
.assertEquals("Merge mode for title should be MergeMode.FIRST", MergeMode
.FIRST
, bookMergeStrategy
.getMergeMode("title"));
180 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
183 public void testGetSetMergeMode() {
186 bookMergeStrategy
.setMergeMode("edition", MergeMode
.SECOND
);
187 Assert
.assertEquals("Merge mode for edition should be", MergeMode
.SECOND
, bookMergeStrategy
.getMergeMode("edition"));
188 } catch (MergeException e1
) {
193 bookMergeStrategy
.setMergeMode("xxx", MergeMode
.SECOND
);
194 Assert
.fail("A property name must exist, otherwise an exception must be thrown");
195 } catch (Exception e
) {
200 bookMergeStrategy
.setMergeMode("cacheStrategy", MergeMode
.SECOND
);
201 Assert
.fail("CacheStrategy is transient and therefore not a legal merge parameter");
202 } catch (Exception e
) {
207 bookMergeStrategy
.setMergeMode("id", MergeMode
.SECOND
);
208 Assert
.fail("Identifier merge mode must always be MergeMode.FIRST");
209 } catch (Exception e
) {
214 bookMergeStrategy
.setMergeMode("uuid", MergeMode
.SECOND
);
215 Assert
.fail("Identifier merge mode must always be MergeMode.FIRST");
216 } catch (Exception e
) {
225 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
226 * @throws MergeException
229 public void testInvokeReferences() throws MergeException
{
230 INomenclaturalReferenceCacheStrategy
<Book
> cacheStrategy1
= book1
.getCacheStrategy();
231 int id
= book1
.getId();
232 UUID uuid
= book1
.getUuid();
234 bookMergeStrategy
.setMergeMode("edition", MergeMode
.SECOND
);
235 bookMergeStrategy
.setMergeMode("volume", MergeMode
.NULL
);
236 bookMergeStrategy
.setMergeMode("authorTeam", MergeMode
.SECOND
);
237 bookMergeStrategy
.setMergeMode("created", MergeMode
.SECOND
);
238 bookMergeStrategy
.setMergeMode("updated",MergeMode
.NULL
);
239 bookMergeStrategy
.setMergeMode("datePublished", MergeMode
.SECOND
);
240 bookMergeStrategy
.setMergeMode("parsingProblem", MergeMode
.SECOND
);
241 bookMergeStrategy
.setMergeMode("inReference", MergeMode
.SECOND
);
242 bookMergeStrategy
.setMergeMode("lsid", MergeMode
.SECOND
);
244 bookMergeStrategy
.invoke(book1
, book2
);
245 } catch (MergeException e
) {
247 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
249 Assert
.assertEquals("Title should stay the same", title1
, book1
.getTitle());
250 Assert
.assertEquals("Edition should become edition 2", editionString2
, book1
.getEdition());
251 Assert
.assertNull("Volume should be null", book1
.getVolume());
254 Assert
.assertEquals("Has problem must be hasProblem2", hasProblem2
, book1
.getParsingProblem());
255 Assert
.assertEquals("nomenclaturally relevant must have value true (AND semantics)", true, book1
.isNomenclaturallyRelevant() );
259 Assert
.assertSame("AuthorTeam must be the one of book2", team2
, book1
.getAuthorTeam());
260 Assert
.assertSame("In Series must be the one of book2", printSeries2
, book1
.getInSeries());
263 Assert
.assertSame("Cache strategy is transient and shouldn't change therefore", cacheStrategy1
, book1
.getCacheStrategy());
267 Assert
.assertSame("Created must be created2", created2
, book1
.getCreated());
268 //TODO updated should have the actual date if any value has changed
269 Assert
.assertSame("Created must be created2", null, book1
.getUpdated());
270 Assert
.assertSame("Created must be datePublsihed2", datePublished2
, book1
.getDatePublished());
271 //TODO this may not be correct
272 Assert
.assertSame("LSID must be LSID2", lsid2
, book1
.getLsid());
276 // book1.setProblemEnds(end);
277 // book1.setProtectedTitleCache(protectedTitleCache);
279 //annotations -> ADD_CLONE
280 Assert
.assertEquals("Annotations should contain annotations of both books", 2, book1
.getAnnotations().size());
281 boolean cloneExists
= false;
282 for (Annotation annotation
: book1
.getAnnotations()){
283 if (annotation
== this.annotation2
){
284 //Hibernate will not persist the exact same object. Probably this is a bug (the according row in the
285 //M:M table is not deleted and a unique constraints does not allow adding 2 rows with the same annotation_id
286 //This test can be changed once this bug does not exist anymore
287 Assert
.fail("Book1 should contain a clone of annotation2 but contains annotation2 itself");
288 }else if (annotationString2
.equals(annotation
.getText())){
292 Assert
.assertTrue("Book1 should contain a clone of annotation2", cloneExists
);
293 // Assert.assertEquals("Annotations from book2 should be deleted", 0, book2.getAnnotations().size());
296 Assert
.assertSame("Identifier must never be changed", id
, book1
.getId());
297 Assert
.assertSame("Identifier must never be changed", uuid
, book1
.getUuid());
300 Institution school1
= Institution
.NewInstance();
301 Institution school2
= Institution
.NewInstance();
303 Thesis thesis1
= Thesis
.NewInstance(school1
);
304 Thesis thesis2
= Thesis
.NewInstance(school2
);
305 DefaultMergeStrategy thesisStrategy
= DefaultMergeStrategy
.NewInstance(Thesis
.class);
307 thesisStrategy
.setMergeMode("school", MergeMode
.SECOND
);
308 thesisStrategy
.invoke(thesis1
, thesis2
);
309 Assert
.assertSame("school must be school2", school2
, thesis1
.getSchool());
314 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
315 * @throws MergeException
319 public void testInvokeTxonNames() throws MergeException
{
320 IMergeStrategy botNameMergeStrategy
= DefaultMergeStrategy
.NewInstance(BotanicalName
.class);
321 BotanicalName botName1
= BotanicalName
.NewInstance(Rank
.SPECIES());
322 BotanicalName botName2
= BotanicalName
.NewInstance(Rank
.SPECIES());
323 BotanicalName botName3
= BotanicalName
.NewInstance(Rank
.SPECIES());
325 botName1
.setGenusOrUninomial("Genus1");
326 botName1
.setSpecificEpithet("species1");
327 botName1
.setAnamorphic(true);
329 botName2
.setGenusOrUninomial("Genus2");
330 botName2
.setSpecificEpithet("species2");
331 botName2
.setAnamorphic(false);
334 botName2
.addBasionym(botName3
, book1
, "p.22", null);
335 Specimen specimen1
= Specimen
.NewInstance();
336 botName2
.addSpecimenTypeDesignation(specimen1
, SpecimenTypeDesignationStatus
.HOLOTYPE(), book2
, "p.56", "originalNameString", false, true);
339 TaxonNameDescription description1
= TaxonNameDescription
.NewInstance();
340 botName1
.addDescription(description1
);
341 TaxonNameDescription description2
= TaxonNameDescription
.NewInstance();
342 botName2
.addDescription(description2
);
345 Team team1
= Team
.NewInstance();
346 Team team2
= Team
.NewInstance();
347 Person person1
= Person
.NewInstance();
348 botName1
.setCombinationAuthorTeam(team1
);
349 botName2
.setCombinationAuthorTeam(team2
);
352 TaxonBase taxon1
= Taxon
.NewInstance(botName1
, book1
);
353 TaxonBase taxon2
= Taxon
.NewInstance(botName2
, book2
);
356 botNameMergeStrategy
.setMergeMode("combinationAuthorTeam", MergeMode
.SECOND
);
357 botNameMergeStrategy
.setMergeMode("anamorphic", MergeMode
.AND
);
359 // botNameMergeStrategy.invoke(botName1, botName2);
360 } catch (MergeException e
) {
362 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
366 Assert
.assertEquals("Is anamorphic must be false", true && false, botName1
.isAnamorphic());
369 Set
<NameRelationship
> toRelations
= botName1
.getRelationsToThisName();
370 Set
<NameRelationship
> basionymRelations
= new HashSet
<NameRelationship
>();
371 for (NameRelationship toRelation
: toRelations
){
372 if (toRelation
.getType().equals(NameRelationshipType
.BASIONYM())){
373 basionymRelations
.add(toRelation
);
376 Assert
.assertEquals("Number of basionyms must be 1", 1, basionymRelations
.size());
377 Assert
.assertEquals("Basionym must have same reference", book1
, basionymRelations
.iterator().next().getCitation());
378 //TODO merge relation if matches() = true
381 Assert
.assertEquals("Number of specimen type designations must be 1", 1, botName1
.getSpecimenTypeDesignations().size());
382 //TODO add to all names etc.
385 Assert
.assertEquals("Number of descriptions must be 2", 2, botName1
.getDescriptions().size());
388 Assert
.assertEquals("Combination author must be combination author 2", team2
, botName1
.getCombinationAuthorTeam());
391 Assert
.assertEquals("TaxonName of taxon1 must be name1", botName1
, taxon1
.getName());
392 Assert
.assertEquals("TaxonName of taxon2 must be name1", botName1
, taxon2
.getName());
397 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#invoke(eu.etaxonomy.cdm.strategy.merge.IMergable, eu.etaxonomy.cdm.strategy.merge.IMergable)}.
398 * @throws MergeException
401 public void testInvokeAgents() throws MergeException
{
402 IMergeStrategy teamMergeStrategy
= DefaultMergeStrategy
.NewInstance(Team
.class);
404 Team team1
= Team
.NewInstance();
405 Team team2
= Team
.NewInstance();
406 Team team3
= Team
.NewInstance();
408 Person person1
= Person
.NewTitledInstance("person1");
409 Person person2
= Person
.NewTitledInstance("person2");
410 Person person3
= Person
.NewTitledInstance("person3");
412 team1
.setTitleCache("Team1");
413 team1
.setNomenclaturalTitle("T.1");
414 String street1
= "Strasse1";
415 team1
.setContact(Contact
.NewInstance(street1
, "12345", "Berlin", WaterbodyOrCountry
.ARGENTINA_ARGENTINE_REPUBLIC(),"pobox" , "Region", "a@b.de", "f12345", "+49-30-123456", "www.abc.de", Point
.NewInstance(2.4, 3.2, ReferenceSystem
.WGS84(), 3)));
416 team2
.setContact(Contact
.NewInstance("Street2", null, "London", null, null, null, null, "874599873", null, null, null));
417 String street3
= "Street3";
418 team2
.addAddress(street3
, null, null, null, null, null, Point
.NewInstance(1.1, 2.2, null, 4));
419 String emailAddress1
= "Email1";
420 team1
.addEmailAddress(emailAddress1
);
422 team2
.addTeamMember(person1
);
423 team2
.addTeamMember(person2
);
424 String emailAddress2
= "Email2";
425 team2
.addEmailAddress(emailAddress2
);
427 team3
.addTeamMember(person3
);
428 team3
.addEmailAddress("emailAddress3");
430 teamMergeStrategy
.invoke(team2
, team3
);
432 Assert
.assertEquals("Team2 must have 3 persons as members",3, team2
.getTeamMembers().size());
433 Assert
.assertTrue("Team2 must have person3 as new member", team2
.getTeamMembers().contains(person3
));
434 Assert
.assertSame("Team2 must have person3 as third member",person3
, team2
.getTeamMembers().get(2));
437 teamMergeStrategy
.invoke(team2
, team1
);
438 Contact team2Contact
= team2
.getContact();
439 Assert
.assertNotNull("team2Contact must not be null", team2Contact
);
440 Assert
.assertNotNull("Addresses must not be null", team2Contact
.getAddresses());
441 Assert
.assertEquals("Number of addresses must be 3", 3, team2Contact
.getAddresses().size());
442 Assert
.assertEquals("Number of email addresses must be 4", 4, team2Contact
.getEmailAddresses().size());
444 boolean street1Exists
= false;
445 boolean street3Exists
= false;
446 boolean country1Exists
= false;
447 for (Address address
: team2Contact
.getAddresses()){
448 if (street1
.equals(address
.getStreet())){
449 street1Exists
= true;
451 if (street3
.equals(address
.getStreet())){
452 street3Exists
= true;
454 if (WaterbodyOrCountry
.ARGENTINA_ARGENTINE_REPUBLIC() == address
.getCountry()){
455 country1Exists
= true;
458 Assert
.assertTrue("Street1 must be one of the streets in team2's addresses", street1Exists
);
459 Assert
.assertTrue("Street3 must be one of the streets in team2's addressesss", street3Exists
);
460 Assert
.assertTrue("Argentina must be one of the countries in team2's addresses", country1Exists
);
463 Institution institution1
= Institution
.NewInstance();
464 institution1
.setTitleCache("inst1");
465 Institution institution2
= Institution
.NewInstance();
466 institution2
.setTitleCache("inst2");
468 TimePeriod period1
= TimePeriod
.NewInstance(2002, 2004);
469 TimePeriod period2
= TimePeriod
.NewInstance(2004, 2006);
471 person1
.addInstitutionalMembership(institution1
, period1
, "departement1", "role1");
472 person2
.addInstitutionalMembership(institution2
, period2
, "departement2", "role2");
474 Keyword keyword1
= Keyword
.NewInstance("K1", "K1", "K1");
475 person1
.addKeyword(keyword1
);
477 Keyword keyword2
= Keyword
.NewInstance("K2", "K2", "K2");
478 person2
.addKeyword(keyword2
);
480 IMergeStrategy personMergeStrategy
= DefaultMergeStrategy
.NewInstance(Person
.class);
481 personMergeStrategy
.invoke(person1
, person2
);
483 Assert
.assertEquals("Number of institutional memberships must be 2", 2, person1
.getInstitutionalMemberships().size());
484 Assert
.assertEquals("Number of keywords must be 2", 2, person1
.getKeywords().size());
485 for (InstitutionalMembership institutionalMembership
: person1
.getInstitutionalMemberships()){
486 Assert
.assertSame("Person of institutional memebership must be person1", person1
, institutionalMembership
.getPerson());