remove duplicate for Argentina
[cdmlib.git] / cdmlib-model / src / test / java / eu / etaxonomy / cdm / strategy / merge / DefaultMergeStrategyTest.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.strategy.merge;
12
13 import java.util.HashSet;
14 import java.util.Set;
15 import java.util.UUID;
16
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;
26
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;
54
55 /**
56 * @author a.mueller
57 * @created 03.08.2009
58 * @version 1.0
59 */
60 public class DefaultMergeStrategyTest {
61 @SuppressWarnings("unused")
62 private static final Logger logger = Logger.getLogger(DefaultMergeStrategyTest.class);
63
64 private DefaultMergeStrategy bookMergeStrategy;
65 private Reference book1;
66 private String editionString1 ="Ed.1";
67 private String volumeString1 ="Vol.1";
68 private Team team1;
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;
74 private LSID lsid1;
75
76 private Reference book2;
77 private String editionString2 ="Ed.2";
78 private String volumeString2 ="Vol.2";
79 private Team team2;
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;
87 private LSID lsid2;
88 private ReferenceFactory refFactory;
89
90
91 private Reference book3;
92
93 /**
94 * @throws java.lang.Exception
95 */
96 @BeforeClass
97 public static void setUpBeforeClass() throws Exception {
98 DefaultTermInitializer termInitializer = new DefaultTermInitializer();
99 termInitializer.initialize();
100 }
101
102 /**
103 * @throws java.lang.Exception
104 */
105 @AfterClass
106 public static void tearDownAfterClass() throws Exception {
107 }
108
109 /**
110 * @throws java.lang.Exception
111 */
112 @Before
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);
125
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);
138
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);
152
153 }
154
155 /**
156 * @throws java.lang.Exception
157 */
158 @After
159 public void tearDown() throws Exception {
160 }
161
162 //********************* TEST *********************************************/
163
164 /**
165 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#NewInstance(java.lang.Class)}.
166 */
167 @Test
168 public void testNewInstance() {
169 Assert.assertNotNull(bookMergeStrategy);
170 Assert.assertEquals(Reference.class, bookMergeStrategy.getMergeClass());
171 }
172
173 /**
174 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
175 */
176 @Test
177 public void testGetMergeMode() {
178 Assert.assertEquals("Merge mode for title should be MergeMode.FIRST", MergeMode.FIRST, bookMergeStrategy.getMergeMode("title"));
179 }
180
181 /**
182 * Test method for {@link eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy#getMergeMode(java.lang.String)}.
183 */
184 @Test
185 public void testGetSetMergeMode() {
186 //legal value
187 try {
188 bookMergeStrategy.setMergeMode("edition", MergeMode.SECOND);
189 Assert.assertEquals("Merge mode for edition should be", MergeMode.SECOND, bookMergeStrategy.getMergeMode("edition"));
190 } catch (MergeException e1) {
191 Assert.fail();
192 }
193 //illegalValue
194 try {
195 bookMergeStrategy.setMergeMode("xxx", MergeMode.SECOND);
196 Assert.fail("A property name must exist, otherwise an exception must be thrown");
197 } catch (Exception e) {
198 //ok
199 }
200 //illegalValue
201 try {
202 bookMergeStrategy.setMergeMode("cacheStrategy", MergeMode.SECOND);
203 Assert.fail("CacheStrategy is transient and therefore not a legal merge parameter");
204 } catch (Exception e) {
205 //ok
206 }
207 //illegalValue
208 try {
209 bookMergeStrategy.setMergeMode("id", MergeMode.SECOND);
210 Assert.fail("Identifier merge mode must always be MergeMode.FIRST");
211 } catch (Exception e) {
212 //ok
213 }
214 //illegalValue
215 try {
216 bookMergeStrategy.setMergeMode("uuid", MergeMode.SECOND);
217 Assert.fail("Identifier merge mode must always be MergeMode.FIRST");
218 } catch (Exception e) {
219 //ok
220 }
221
222
223 }
224
225
226 /**
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
229 */
230 @Test
231 public void testInvokeReferences() throws MergeException {
232 INomenclaturalReferenceCacheStrategy<Reference> cacheStrategy1 = (INomenclaturalReferenceCacheStrategy<Reference>)book1.getCacheStrategy();
233 int id = book1.getId();
234 UUID uuid = book1.getUuid();
235 try {
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);
245
246 bookMergeStrategy.invoke(book1, book2);
247 } catch (MergeException e) {
248 throw e;
249 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
250 }
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());
254
255 //Boolean
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() );
258
259
260 //CdmBase
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());
263
264 //Transient
265 Assert.assertSame("Cache strategy is transient and shouldn't change therefore", cacheStrategy1, book1.getCacheStrategy());
266
267
268 //UserType
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());
275
276
277 //TODO
278 // book1.setProblemEnds(end);
279 // book1.setProtectedTitleCache(protectedTitleCache);
280
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())){
291 cloneExists = true;
292 }
293 }
294 Assert.assertTrue("Book1 should contain a clone of annotation2", cloneExists);
295 // Assert.assertEquals("Annotations from book2 should be deleted", 0, book2.getAnnotations().size());
296
297 //identifier
298 Assert.assertSame("Identifier must never be changed", id, book1.getId());
299 Assert.assertSame("Identifier must never be changed", uuid, book1.getUuid());
300
301 //Test Thesis
302 Institution school1 = Institution.NewInstance();
303 Institution school2 = Institution.NewInstance();
304
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);
311
312 thesisStrategy.setMergeMode("school", MergeMode.SECOND);
313 thesisStrategy.invoke(thesis1, thesis2);
314 Assert.assertSame("school must be school2", school2, thesis1.getSchool());
315 }
316
317
318 /**
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
321 */
322 @Test
323 //@Ignore
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());
329
330 botName1.setGenusOrUninomial("Genus1");
331 botName1.setSpecificEpithet("species1");
332 botName1.setAnamorphic(true);
333
334 botName2.setGenusOrUninomial("Genus2");
335 botName2.setSpecificEpithet("species2");
336 botName2.setAnamorphic(false);
337
338 //name relations
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);
342
343 //descriptions
344 TaxonNameDescription description1 = TaxonNameDescription.NewInstance();
345 botName1.addDescription(description1);
346 TaxonNameDescription description2 = TaxonNameDescription.NewInstance();
347 botName1.addDescription(description2);
348
349 //authors
350 Team team1 = Team.NewInstance();
351 Team team2 = Team.NewInstance();
352 Person person1 = Person.NewInstance();
353 botName1.setCombinationAuthorTeam(team1);
354 botName2.setCombinationAuthorTeam(team2);
355
356 //taxa
357 TaxonBase taxon1= Taxon.NewInstance(botName1, book1);
358 TaxonBase taxon2= Taxon.NewInstance(botName2, book2);
359
360 try {
361 botNameMergeStrategy.setMergeMode("combinationAuthorTeam", MergeMode.SECOND);
362 botNameMergeStrategy.setMergeMode("anamorphic", MergeMode.AND);
363
364 // botNameMergeStrategy.invoke(botName1, botName2);
365 } catch (MergeException e) {
366 throw e;
367 //Assert.fail("An unexpected merge exception occurred: " + e.getMessage() + ";" + e.getCause().getMessage());
368 }
369
370 //Boolean
371 Assert.assertEquals("Is anamorphic must be false", true && false, botName2.isAnamorphic());
372
373 //NameRelations
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);
379 }
380 }
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
384
385 //Types
386 Assert.assertEquals("Number of specimen type designations must be 1", 1, botName2.getSpecimenTypeDesignations().size());
387 //TODO add to all names etc.
388
389 //Description
390 Assert.assertEquals("Number of descriptions must be 2", 2, botName1.getDescriptions().size());
391
392 //AuthorTeams
393 Assert.assertEquals("Combination author must be combination author 1", team1, botName1.getCombinationAuthorTeam());
394
395 //Taxa
396 Assert.assertEquals("TaxonName of taxon1 must be name1", botName1, taxon1.getName());
397 Assert.assertEquals("TaxonName of taxon2 must be name2", botName2, taxon2.getName());
398
399 }
400
401 /**
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
404 */
405 @Test
406 public void testInvokeAgents() throws MergeException {
407 IMergeStrategy teamMergeStrategy = DefaultMergeStrategy.NewInstance(Team.class);
408
409 Team team1 = Team.NewInstance();
410 Team team2 = Team.NewInstance();
411 Team team3 = Team.NewInstance();
412
413 Person person1 = Person.NewTitledInstance("person1");
414 Person person2 = Person.NewTitledInstance("person2");
415 Person person3 = Person.NewTitledInstance("person3");
416
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);
426
427 team2.addTeamMember(person1);
428 team2.addTeamMember(person2);
429 String emailAddress2 = "Email2";
430 team2.addEmailAddress(emailAddress2);
431
432 team3.addTeamMember(person3);
433 team3.addEmailAddress("emailAddress3");
434
435 teamMergeStrategy.invoke(team2, team3);
436
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));
440
441 //Contact
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());
448
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;
455 }
456 if (street3.equals(address.getStreet())){
457 street3Exists = true;
458 }
459 if (WaterbodyOrCountry.ARGENTINAARGENTINEREPUBLIC() == address.getCountry()){
460 country1Exists = true;
461 }
462 }
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);
466
467 //Person
468 Institution institution1 = Institution.NewInstance();
469 institution1.setTitleCache("inst1", true);
470 Institution institution2 = Institution.NewInstance();
471 institution2.setTitleCache("inst2", true);
472
473 TimePeriod period1 = TimePeriod.NewInstance(2002, 2004);
474 TimePeriod period2 = TimePeriod.NewInstance(2004, 2006);
475
476 person1.addInstitutionalMembership(institution1, period1, "departement1", "role1");
477 person2.addInstitutionalMembership(institution2, period2, "departement2", "role2");
478
479 IMergeStrategy personMergeStrategy = DefaultMergeStrategy.NewInstance(Person.class);
480 personMergeStrategy.invoke(person1, person2);
481
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());
485 }
486
487 }
488
489 }