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