ref #8162 move OriginalSourceXXX to reference package
[cdmlib.git] / cdmlib-persistence / src / test / java / eu / etaxonomy / cdm / persistence / dao / hibernate / statistics / StatisticsDaoHibernateImplTest.java
1 package eu.etaxonomy.cdm.persistence.dao.hibernate.statistics;
2
3 import static org.junit.Assert.assertTrue;
4
5 import java.io.FileNotFoundException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Random;
13 import java.util.Set;
14 import java.util.UUID;
15
16 import org.apache.commons.lang.RandomStringUtils;
17 import org.apache.log4j.Logger;
18 import org.junit.After;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.unitils.spring.annotation.SpringBeanByType;
22
23 import eu.etaxonomy.cdm.model.common.Language;
24 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
25 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
26 import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
27 import eu.etaxonomy.cdm.model.description.TaxonDescription;
28 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
29 import eu.etaxonomy.cdm.model.description.TextData;
30 import eu.etaxonomy.cdm.model.name.IBotanicalName;
31 import eu.etaxonomy.cdm.model.name.Rank;
32 import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
33 import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
34 import eu.etaxonomy.cdm.model.reference.Reference;
35 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
36 import eu.etaxonomy.cdm.model.taxon.Classification;
37 import eu.etaxonomy.cdm.model.taxon.Synonym;
38 import eu.etaxonomy.cdm.model.taxon.SynonymType;
39 import eu.etaxonomy.cdm.model.taxon.Taxon;
40 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
41 import eu.etaxonomy.cdm.model.view.context.AuditEventContextHolder;
42 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
43 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionElementDao;
44 import eu.etaxonomy.cdm.persistence.dao.reference.IReferenceDao;
45 import eu.etaxonomy.cdm.persistence.dao.statistics.IStatisticsDao;
46 import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
47 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
48 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
49 import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
50
51 public class StatisticsDaoHibernateImplTest
52 extends CdmTransactionalIntegrationTest {
53
54 private static final Logger logger = Logger.getLogger(StatisticsDaoHibernateImplTest.class);
55
56 @SpringBeanByType
57 private IStatisticsDao statisticsDao;
58
59 private UUID nodeUuid;
60
61 private List<Classification> classifications;
62
63
64
65 // choose a number
66 private static final int NO_OF_ACCEPTED_TAXA = 10;
67
68 // choose a number (less than NO_OF_ACCEPTED_TAXA)
69 private static final int NO_OF_CLASSIFICATIONS = 3;
70
71 // must be less or equal to NO_OF_ACCEPTED_TAXA
72 private static final int NO_OF_SYNONYMS = 7;
73
74 // taxa that occure in several classifications:
75 // must NOT be more than NO_OF_ACCEPTED_TAXA
76 private static final int NO_OF_SHARED_TAXA = 4;
77
78 // must be NO_OF_ACCEPTED_TAXA + NO_OF_SYNONYMS
79 private static final int NO_OF_ALLTAXA = NO_OF_ACCEPTED_TAXA
80 + NO_OF_SYNONYMS;
81
82 // must be NO_OF_ACCEPTED_TAXA+NO_OF_SYNONYMS
83 private static final int NO_OF_TAXON_NAMES = NO_OF_ACCEPTED_TAXA
84 + NO_OF_SYNONYMS;
85
86 // this represents an approx. no of the amount that will actually generated!
87 private static final int NO_OF_DESCRIPTIVE_SOURCE_REFERENCES = 16;
88
89 // private static final int NO_OF_ALL_REFERENCES = NO_OF_ACCEPTED_TAXA + 0;
90
91 // must not be more than NO_OF_ACCEPTED_TAXA+NO_OF_SYNONYMS
92 private static final int NO_OF_NOMENCLATURAL_REFERENCES = NO_OF_ACCEPTED_TAXA
93 + NO_OF_SYNONYMS - 4;
94
95 // --------------------variables for all ------------------
96
97 private Long no_of_all_references = new Long(0);
98 private Long no_of_descriptive_source_references = new Long(0);
99
100 // ............................................
101
102 // log the type enum to an int constant:
103 private Map<String, Long> typeMap_ALL;
104
105 // ------------------ variables for CLASSIFICATIONS -----------------------
106
107 // int[] anArray = new int[NO_OF_CLASSIFICATIONS];
108 private static List<Long> no_of_all_taxa_c = new ArrayList<Long>(
109 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
110 private static List<Long> no_of_accepted_taxa_c = new ArrayList<Long>(
111 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
112 private static List<Long> no_of_synonyms_c = new ArrayList<Long>(
113 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
114 private static List<Long> no_of_taxon_names_c = new ArrayList<Long>(
115 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
116 private static List<Long> no_of_descriptive_source_references_c = new ArrayList<Long>(
117 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
118 private static List<Long> no_of_all_references_c = new ArrayList<Long>(
119 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
120 private static List<Long> no_of_nomenclatural_references_c = new ArrayList<Long>(
121 Collections.nCopies(NO_OF_CLASSIFICATIONS, new Long(0)));
122 // we do not count classifications in classifications
123
124 // ........................... constant map ..........................
125
126 private static final Map<String, List<Long>> typeCountMap_CLASSIFICATION = new HashMap<String, List<Long>>() {
127 {
128 put("CLASSIFICATION",
129 new ArrayList<Long>(Arrays.asList((Long) null, null, null)));
130 put("ALL_TAXA", no_of_all_taxa_c);
131 put("ACCEPTED_TAXA", no_of_accepted_taxa_c);
132 put("SYNONYMS", no_of_synonyms_c);
133 put("TAXON_NAMES", no_of_taxon_names_c);
134 put("DESCRIPTIVE_SOURCE_REFERENCES",
135 no_of_descriptive_source_references_c);
136 put("ALL_REFERENCES", no_of_all_references_c);
137 put("NOMENCLATURAL_REFERENCES", no_of_nomenclatural_references_c);
138 }
139 };
140
141 // ****************** services: ************************
142 @SpringBeanByType
143 private IStatisticsDao service;
144 @SpringBeanByType
145 private IClassificationDao classificationDao;
146 @SpringBeanByType
147 private ITaxonDao taxonDao;
148 @SpringBeanByType
149 private IReferenceDao referenceDao;
150 @SpringBeanByType
151 private IDescriptionDao descriptionDao;
152 @SpringBeanByType
153 private IDescriptionElementDao descriptionElementDao;
154 @SpringBeanByType
155 private ITaxonNodeDao taxonNodeDao;
156
157
158 @Before
159 public void setUp() {
160 // nodeUuid =UUID.fromString("46cd7e78-f7d5-4c31-937b-2bc5074618c4");
161 nodeUuid = UUID.fromString("0b5846e5-b8d2-4ca9-ac51-099286ea4adc");
162
163 AuditEventContextHolder.clearContext();
164
165 }
166
167 @After
168 public void tearDown() {
169 AuditEventContextHolder.clearContext();
170 }
171
172 @Test
173 // @DataSet
174 public void testGetAllChildNodes() {
175 List<UUID> result;
176 createDataSet();
177 for (Classification classification : classifications) {
178 TaxonNode root;
179 root= createTaxTree(classification);
180
181 result=statisticsDao.getAllChildNodeIds(root.getUuid());
182 logger.debug("classification "+ classification.getName()+": ");
183 logger.debug("result: "+result.toString());
184
185 }
186 if (logger.isTraceEnabled()) {
187 print();
188 }
189 // result=statisticsDao.getAllTaxonIds(nodeUuid);
190 // statisticsDao.getAllTaxonIds();
191 assertTrue(true);
192 // fail("Not yet implemented");
193 }
194
195 private void createDataSet() {
196 // create NO_OF_CLASSIFICATIONS classifications
197 classifications = new ArrayList<Classification>();
198
199 for (int i = 1; i <= NO_OF_CLASSIFICATIONS; i++) {
200 Classification classification = Classification
201 .NewInstance("European Abies" + i);
202 classifications.add(classification);
203 classificationDao.save(classification);
204 }
205 // create all taxa, references and synonyms and attach them to one or
206 // more classifications
207
208 // variables: flags
209 int remainder = NO_OF_ACCEPTED_TAXA;
210 Reference sec = ReferenceFactory.newBook();
211 boolean secondClassificationForTaxonFlag = false;
212 boolean synonymFlag = false;
213 boolean tNomRefFlag = false;
214 boolean sNomRefFlag = false;
215 boolean tDescrSourceRefFlag = false;
216 boolean sDescrSourceRefFlag = false;
217
218 // variables: counter (pre-loop)
219 int descriptiveElementsPerTaxon = (NO_OF_DESCRIPTIVE_SOURCE_REFERENCES / NO_OF_ACCEPTED_TAXA) + 1;
220
221 int taxaInClass;
222 int classiCounter = 0, sharedClassification = 0, synonymCounter = 0, nomRefCounter = 0;
223
224 // iterate over classifications and add taxa
225 for (/* see above */; remainder > 0
226 && classiCounter < NO_OF_CLASSIFICATIONS; /* see below */) {
227
228 // compute no of taxa to be created in this classification
229 if (classiCounter >= NO_OF_CLASSIFICATIONS - 1) { // last
230 // classification
231 // gets all left
232 // taxa
233 taxaInClass = remainder;
234 } else { // take half of left taxa for this class:
235 taxaInClass = remainder / 2;
236 }
237
238 // iterate over amount of taxa meant to be in this classification
239 for (int taxonCounter = 1; taxonCounter <= taxaInClass; taxonCounter++) {
240
241 // create a String for the Name
242 RandomStringUtils.randomAlphabetic(10);
243 String randomName = RandomStringUtils.randomAlphabetic(5) + " "
244 + RandomStringUtils.randomAlphabetic(10);
245
246 // create a name for the taxon
247 IBotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
248 name.setNameCache(randomName, true);
249
250 // create nomenclatural reference for taxon name (if left)
251 if (nomRefCounter < NO_OF_NOMENCLATURAL_REFERENCES) {
252 // we remember this taxon has a nomenclatural reference:
253 tNomRefFlag = true;
254 Reference nomRef = ReferenceFactory.newBook();
255 name.setNomenclaturalReference(nomRef);
256 referenceDao.save(nomRef);
257 nomRefCounter++;
258 }
259
260 // create a new sec for every other taxon
261 if (taxonCounter % 2 != 0) {
262 sec = createSecReference(classiCounter, taxonCounter);
263 }
264
265 // create the taxon
266 Taxon taxon = Taxon.NewInstance(name, sec);
267
268 // create descriptions, description sources and their references
269
270 if (no_of_descriptive_source_references < NO_OF_DESCRIPTIVE_SOURCE_REFERENCES) {
271
272 tDescrSourceRefFlag = true;
273
274 // create a description and 2 description elements with
275 // references for taxon name
276 TaxonNameDescription nameDescr = TaxonNameDescription.NewInstance();
277 CommonTaxonName nameElement = CommonTaxonName.NewInstance(
278 "Veilchen" + taxonCounter, Language.GERMAN());
279 TextData textElement = new TextData();
280 Reference nameElementRef = ReferenceFactory.newArticle();
281 Reference textElementRef = ReferenceFactory
282 .newBookSection();
283 nameElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, nameElementRef, "name: ");
284 textElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, textElementRef, "text: ");
285 nameDescr.addElement(nameElement);
286 nameDescr.addElement(textElement);
287 name.addDescription(nameDescr);
288 // taxon.getName().addDescription(nameDescr);
289 referenceDao.save(nameElementRef);
290 referenceDao.save(textElementRef);
291 descriptionDao.save(nameDescr);
292
293 // create descriptions, description sources and their
294 // references
295 // for taxon
296 TaxonDescription taxonDescription = new TaxonDescription();
297 for (int i = 0; i < descriptiveElementsPerTaxon; i++) {
298 DescriptionElementBase descriptionElement = new TextData();
299 DescriptionElementSource descriptionElementSource = DescriptionElementSource
300 .NewInstance(OriginalSourceType.PrimaryTaxonomicSource);
301 Reference article = ReferenceFactory.newArticle();
302
303 descriptionElementSource.setCitation(article);
304 descriptionElement.addSource(descriptionElementSource);
305 taxonDescription.addElement(descriptionElement);
306 referenceDao.save(article);
307 descriptionElementDao.save(descriptionElement);
308
309 }
310 descriptionDao.save(taxonDescription);
311 taxon.addDescription(taxonDescription);
312
313 // create a Specimen for taxon with description, descr.
314 // element and referece
315 //
316 // Specimen specimen = Specimen.NewInstance();
317 // SpecimenDescription specimenDescription =
318 // SpecimenDescription.NewInstance(specimen);
319 // DescriptionElementBase descrElement = new TextData();
320 // Reference specimenRef = ReferenceFactory.newArticle();
321 // descrElement.addSource(null, null, specimenRef, null);
322 //
323 //
324 // descriptionService.save(specimenDescription);
325 // taxon.add(specimen);
326
327 no_of_descriptive_source_references += descriptiveElementsPerTaxon + 2 + 1;
328
329 }
330
331 // add taxon to classification
332 classifications.get(classiCounter).addChildTaxon(taxon, null, null);
333
334 // now if there are any left, we create a synonym for the taxon
335 if (synonymCounter < NO_OF_SYNONYMS) {
336 synonymFlag = true;
337 randomName = RandomStringUtils.randomAlphabetic(5) + " "
338 + RandomStringUtils.randomAlphabetic(10);
339 // name for synonym
340 name = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
341 name.setNameCache(randomName, true);
342
343 // create nomenclatural reference for synonym name (if left)
344 if (nomRefCounter < NO_OF_NOMENCLATURAL_REFERENCES) {
345 sNomRefFlag = true;
346 Reference nomRef = ReferenceFactory.newBook();
347 name.setNomenclaturalReference(nomRef);
348 referenceDao.save(nomRef);
349 nomRefCounter++;
350 }
351
352 if (no_of_descriptive_source_references < NO_OF_DESCRIPTIVE_SOURCE_REFERENCES) {
353 sDescrSourceRefFlag = true;
354
355 // create a description and 2 description elements with
356 // references for synonym name
357 TaxonNameDescription nameDescr = TaxonNameDescription.NewInstance();
358 CommonTaxonName nameElement = CommonTaxonName
359 .NewInstance("anderes Veilchen" + taxonCounter,
360 Language.GERMAN());
361 TextData textElement = new TextData();
362 Reference nameElementRef = ReferenceFactory.newArticle();
363 Reference textElementRef = ReferenceFactory.newBookSection();
364 nameElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, nameElementRef,"name: ");
365 textElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, textElementRef,"text: ");
366 nameDescr.addElement(nameElement);
367 nameDescr.addElement(textElement);
368 name.addDescription(nameDescr);
369 // taxon.getName().addDescription(nameDescr);
370 referenceDao.save(nameElementRef);
371 referenceDao.save(textElementRef);
372 descriptionDao.save(nameDescr);
373 no_of_descriptive_source_references += 2;
374 }
375
376 // create a new reference for every other synonym:
377 if (taxonCounter % 2 != 0) {
378 sec = createSecReference(classiCounter, taxonCounter);
379 }
380 Synonym synonym = Synonym.NewInstance(name, sec);
381 taxonDao.save(synonym);
382 taxon.addSynonym(synonym,
383 SynonymType.SYNONYM_OF());
384
385 synonymCounter++;
386 }
387
388 // if this is not the last classification and there are
389 // taxa left that should be in more than one classification
390 // we add the taxon to the next class in the list too.
391 if (classiCounter < NO_OF_CLASSIFICATIONS
392 && sharedClassification < NO_OF_SHARED_TAXA) {
393 classifications.get(classiCounter + 1).addChildTaxon(taxon, null, null);
394
395 // we remember that this taxon is attached to 2
396 // classifications:
397 secondClassificationForTaxonFlag = true;
398 sharedClassification++;
399 classificationDao.saveOrUpdate(classifications
400 .get(classiCounter + 1));
401 }
402
403 taxonDao.save(taxon);
404 classificationDao.saveOrUpdate(classifications
405 .get(classiCounter));
406
407 // count the data created with this taxon:
408 int c = classiCounter;
409
410 if (secondClassificationForTaxonFlag) {
411 c++;
412 }
413
414 // run the following loop once, if this taxon only belongs to
415 // one
416 // classification.
417 // twice, if it is attached to 2 classifications
418 for (int i = classiCounter; i <= c; i++) {
419
420 // count everything just created for this taxon:
421 increment(no_of_accepted_taxa_c, i);
422 increment(no_of_taxon_names_c, i);
423 if (tNomRefFlag) {
424 increment(no_of_nomenclatural_references_c, i);
425 }
426 if (sNomRefFlag) {
427 increment(no_of_nomenclatural_references_c, i);
428 }
429 if (synonymFlag) {
430 increment(no_of_synonyms_c, i);
431 increment(no_of_taxon_names_c, i);
432 }
433 if (taxonCounter % 2 != 0) {
434 increment(no_of_all_references_c, i);
435 if (synonymFlag) {
436 increment(no_of_all_references_c, i);
437 }
438 }
439 if (tDescrSourceRefFlag) {
440 increment(no_of_descriptive_source_references_c, i,
441 descriptiveElementsPerTaxon + 2);
442 }
443
444 if (sDescrSourceRefFlag) {
445 increment(no_of_descriptive_source_references_c, i, 2);
446 }
447 }
448 // put flags back:
449 secondClassificationForTaxonFlag = false;
450 tNomRefFlag = false;
451 sNomRefFlag = false;
452 synonymFlag = false;
453 tDescrSourceRefFlag = false;
454 sDescrSourceRefFlag = false;
455 }
456
457 // modify variables (post-loop)
458 classiCounter++;
459 remainder -= taxaInClass;
460
461 }
462 merge(no_of_accepted_taxa_c, no_of_synonyms_c, no_of_all_taxa_c);
463 merge(no_of_all_references_c, no_of_nomenclatural_references_c,
464 no_of_all_references_c);
465
466 // TODO Auto-generated method stub
467
468 }
469
470 /**
471 * create and count a new sec Reference
472 *
473 * @param classiCounter
474 * @param taxonCounter
475 * @return
476 */
477 private Reference createSecReference(int classiCounter, int taxonCounter) {
478 Reference sec;
479 sec = ReferenceFactory.newBook();
480 sec.setTitle("book " + classiCounter + "." + taxonCounter);
481 referenceDao.save(sec);
482 no_of_all_references++;
483 return sec;
484 }
485
486 /**
487 * @param no_of_sth
488 * @param inClassification
489 * @param increase
490 */
491 private void increment(List<Long> no_of_sth, int inClassification,
492 int increase) {
493 no_of_sth.set(inClassification, (no_of_sth.get(inClassification))
494 + increase);
495 }
496
497 private void increment(List<Long> no_of_sth, int inClassification) {
498 increment(no_of_sth, inClassification, 1);
499 }
500
501 private void merge(List<Long> no_of_sth1, List<Long> no_of_sth2,
502 List<Long> no_of_sum) {
503
504 for (int i = 0; i < NO_OF_CLASSIFICATIONS; i++) {
505 Long sum = no_of_sth1.get(i) + no_of_sth2.get(i);
506 no_of_sum.set(i, sum);
507
508 }
509 }
510
511 private TaxonNode createTaxTree(Classification classification) {
512 Random rand = new Random();
513
514 Set<TaxonNode> nodes = classification.getAllNodes();
515 ArrayList<TaxonNode> children = new ArrayList<>();
516 TaxonNode parent = nodes.iterator().next();
517
518 TaxonNode root = parent;
519 nodes.remove(parent);
520 while (!nodes.isEmpty()) {
521 int n = rand.nextInt(2) + 1;
522 for (int i = 1; i <= n && !(nodes.isEmpty()); i++) {
523 TaxonNode nextNode = nodes.iterator().next();
524 nextNode = parent.addChildNode(nextNode, null, null);
525 children.add(nextNode);
526 nodes.remove(nextNode);
527 }
528
529 parent = children.get(0);
530 children.remove(0);
531 }
532
533 return root;
534 }
535
536 /**
537 *
538 */
539 private void print() {
540 for (Classification classification : classifications) {
541 System.out.println("Classification:" + classification.toString());
542 for (TaxonNode node : classification.getAllNodes()) {
543 System.out.println("\tTaxon: " + node.getTaxon().toString()+" node UUID: "+ node.getUuid());
544 System.out.println(" \t(Name: "
545 + node.getTaxon().getName().toString() + ")");
546 System.out.print("\tChildren: ");
547 for (TaxonNode childNode : node.getChildNodes()) {
548 System.out.print(/*childNode.getTaxon().getName() + */" node UUID: "+ node.getUuid()+" ");
549 }
550 System.out.println();
551
552 if (node.getTaxon().getName().getNomenclaturalReference() != null) {
553 System.out.println(" \t(Nomencl. Ref.: "
554 + node.getTaxon().getName()
555 .getNomenclaturalReference().getId() + ")");
556 }
557 for (Synonym synonym : node.getTaxon().getSynonyms()) {
558 System.out.println("\t\tSynonym: " + synonym.toString());
559 System.out.println(" \t\t(Name: "
560 + synonym.getName().toString() + ")");
561 if (synonym.getName().getNomenclaturalReference() != null) {
562 System.out.println(" \t\t(Nomencl. Ref.: "
563 + synonym.getName().getNomenclaturalReference()
564 .getId() + ")");
565 }
566 System.out.println();
567 }
568 }
569
570 }
571 System.out.println();
572 System.out.println("end!");
573
574 }
575
576 /* (non-Javadoc)
577 * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
578 */
579 @Override
580 public void createTestDataSet() throws FileNotFoundException {
581 // TODO Auto-generated method stub
582
583 }
584 }