Merge remote-tracking branch 'origin/develop' into cdm-4.1
[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 result=statisticsDao.getAllChildNodeIds(root.getUuid());
183 System.out.println("classification "+ classification.getName()+": ");
184 System.out.println("result: "+result.toString());
185 System.out.println("");
186 }
187 if (PRINTOUT) {
188 print();
189 }
190 // result=statisticsDao.getAllTaxonIds(nodeUuid);
191 // statisticsDao.getAllTaxonIds();
192 assertTrue(true);
193 // fail("Not yet implemented");
194 }
195
196 private void createDataSet() {
197 // create NO_OF_CLASSIFICATIONS classifications
198 classifications = new ArrayList<Classification>();
199
200 for (int i = 1; i <= NO_OF_CLASSIFICATIONS; i++) {
201 Classification classification = Classification
202 .NewInstance("European Abies" + i);
203 classifications.add(classification);
204 classificationDao.save(classification);
205 }
206 // create all taxa, references and synonyms and attach them to one or
207 // more classifications
208
209 // variables: flags
210 int remainder = NO_OF_ACCEPTED_TAXA;
211 Reference sec = ReferenceFactory.newBook();
212 boolean secondClassificationForTaxonFlag = false;
213 boolean synonymFlag = false;
214 boolean tNomRefFlag = false;
215 boolean sNomRefFlag = false;
216 boolean tDescrSourceRefFlag = false;
217 boolean sDescrSourceRefFlag = false;
218
219 // variables: counter (pre-loop)
220 int descriptiveElementsPerTaxon = (NO_OF_DESCRIPTIVE_SOURCE_REFERENCES / NO_OF_ACCEPTED_TAXA) + 1;
221
222 int taxaInClass;
223 int classiCounter = 0, sharedClassification = 0, synonymCounter = 0, nomRefCounter = 0;
224
225 // iterate over classifications and add taxa
226 for (/* see above */; remainder > 0
227 && classiCounter < NO_OF_CLASSIFICATIONS; /* see below */) {
228
229 // compute no of taxa to be created in this classification
230 if (classiCounter >= NO_OF_CLASSIFICATIONS - 1) { // last
231 // classification
232 // gets all left
233 // taxa
234 taxaInClass = remainder;
235 } else { // take half of left taxa for this class:
236 taxaInClass = remainder / 2;
237 }
238
239 // iterate over amount of taxa meant to be in this classification
240 for (int taxonCounter = 1; taxonCounter <= taxaInClass; taxonCounter++) {
241
242 // create a String for the Name
243 RandomStringUtils.randomAlphabetic(10);
244 String randomName = RandomStringUtils.randomAlphabetic(5) + " "
245 + RandomStringUtils.randomAlphabetic(10);
246
247 // create a name for the taxon
248 BotanicalName name = BotanicalName.NewInstance(Rank.SPECIES());
249 name.setNameCache(randomName, true);
250
251 // create nomenclatural reference for taxon name (if left)
252 if (nomRefCounter < NO_OF_NOMENCLATURAL_REFERENCES) {
253 // we remember this taxon has a nomenclatural reference:
254 tNomRefFlag = true;
255 Reference nomRef = ReferenceFactory.newBook();
256 name.setNomenclaturalReference(nomRef);
257 referenceDao.save(nomRef);
258 nomRefCounter++;
259 }
260
261 // create a new sec for every other taxon
262 if (taxonCounter % 2 != 0) {
263 sec = createSecReference(classiCounter, taxonCounter);
264 }
265
266 // create the taxon
267 Taxon taxon = Taxon.NewInstance(name, sec);
268
269 // create descriptions, description sources and their references
270
271 if (no_of_descriptive_source_references < NO_OF_DESCRIPTIVE_SOURCE_REFERENCES) {
272
273 tDescrSourceRefFlag = true;
274
275 // create a description and 2 description elements with
276 // references for taxon name
277 TaxonNameDescription nameDescr = TaxonNameDescription.NewInstance();
278 CommonTaxonName nameElement = CommonTaxonName.NewInstance(
279 "Veilchen" + taxonCounter, Language.GERMAN());
280 TextData textElement = new TextData();
281 Reference nameElementRef = ReferenceFactory.newArticle();
282 Reference textElementRef = ReferenceFactory
283 .newBookSection();
284 nameElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, nameElementRef, "name: ");
285 textElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, textElementRef, "text: ");
286 nameDescr.addElement(nameElement);
287 nameDescr.addElement(textElement);
288 name.addDescription(nameDescr);
289 // taxon.getName().addDescription(nameDescr);
290 referenceDao.save(nameElementRef);
291 referenceDao.save(textElementRef);
292 descriptionDao.save(nameDescr);
293
294 // create descriptions, description sources and their
295 // references
296 // for taxon
297 TaxonDescription taxonDescription = new TaxonDescription();
298 for (int i = 0; i < descriptiveElementsPerTaxon; i++) {
299 DescriptionElementBase descriptionElement = new TextData();
300 DescriptionElementSource descriptionElementSource = DescriptionElementSource
301 .NewInstance(OriginalSourceType.PrimaryTaxonomicSource);
302 Reference article = ReferenceFactory.newArticle();
303
304 descriptionElementSource.setCitation(article);
305 descriptionElement.addSource(descriptionElementSource);
306 taxonDescription.addElement(descriptionElement);
307 referenceDao.save(article);
308 descriptionElementDao.save(descriptionElement);
309
310 }
311 descriptionDao.save(taxonDescription);
312 taxon.addDescription(taxonDescription);
313
314 // create a Specimen for taxon with description, descr.
315 // element and referece
316 //
317 // Specimen specimen = Specimen.NewInstance();
318 // SpecimenDescription specimenDescription =
319 // SpecimenDescription.NewInstance(specimen);
320 // DescriptionElementBase descrElement = new TextData();
321 // Reference specimenRef = ReferenceFactory.newArticle();
322 // descrElement.addSource(null, null, specimenRef, null);
323 //
324 //
325 // descriptionService.save(specimenDescription);
326 // taxon.add(specimen);
327
328 no_of_descriptive_source_references += descriptiveElementsPerTaxon + 2 + 1;
329
330 }
331
332 // add taxon to classification
333 classifications.get(classiCounter).addChildTaxon(taxon, null, null);
334
335 // now if there are any left, we create a synonym for the taxon
336 if (synonymCounter < NO_OF_SYNONYMS) {
337 synonymFlag = true;
338 randomName = RandomStringUtils.randomAlphabetic(5) + " "
339 + RandomStringUtils.randomAlphabetic(10);
340 // name for synonym
341 name = BotanicalName.NewInstance(Rank.SPECIES());
342 name.setNameCache(randomName, true);
343
344 // create nomenclatural reference for synonym name (if left)
345 if (nomRefCounter < NO_OF_NOMENCLATURAL_REFERENCES) {
346 sNomRefFlag = true;
347 Reference nomRef = ReferenceFactory.newBook();
348 name.setNomenclaturalReference(nomRef);
349 referenceDao.save(nomRef);
350 nomRefCounter++;
351 }
352
353 if (no_of_descriptive_source_references < NO_OF_DESCRIPTIVE_SOURCE_REFERENCES) {
354 sDescrSourceRefFlag = true;
355
356 // create a description and 2 description elements with
357 // references for synonym name
358 TaxonNameDescription nameDescr = TaxonNameDescription.NewInstance();
359 CommonTaxonName nameElement = CommonTaxonName
360 .NewInstance("anderes Veilchen" + taxonCounter,
361 Language.GERMAN());
362 TextData textElement = new TextData();
363 Reference nameElementRef = ReferenceFactory.newArticle();
364 Reference textElementRef = ReferenceFactory.newBookSection();
365 nameElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, nameElementRef,"name: ");
366 textElement.addSource(OriginalSourceType.PrimaryTaxonomicSource, null, null, textElementRef,"text: ");
367 nameDescr.addElement(nameElement);
368 nameDescr.addElement(textElement);
369 name.addDescription(nameDescr);
370 // taxon.getName().addDescription(nameDescr);
371 referenceDao.save(nameElementRef);
372 referenceDao.save(textElementRef);
373 descriptionDao.save(nameDescr);
374 no_of_descriptive_source_references += 2;
375 }
376
377 // create a new reference for every other synonym:
378 if (taxonCounter % 2 != 0) {
379 sec = createSecReference(classiCounter, taxonCounter);
380 }
381 Synonym synonym = Synonym.NewInstance(name, sec);
382 taxonDao.save(synonym);
383 taxon.addSynonym(synonym,
384 SynonymType.SYNONYM_OF());
385
386 synonymCounter++;
387 }
388
389 // if this is not the last classification and there are
390 // taxa left that should be in more than one classification
391 // we add the taxon to the next class in the list too.
392 if (classiCounter < NO_OF_CLASSIFICATIONS
393 && sharedClassification < NO_OF_SHARED_TAXA) {
394 classifications.get(classiCounter + 1).addChildTaxon(taxon, null, null);
395
396 // we remember that this taxon is attached to 2
397 // classifications:
398 secondClassificationForTaxonFlag = true;
399 sharedClassification++;
400 classificationDao.saveOrUpdate(classifications
401 .get(classiCounter + 1));
402 }
403
404 taxonDao.save(taxon);
405 classificationDao.saveOrUpdate(classifications
406 .get(classiCounter));
407
408 // count the data created with this taxon:
409 int c = classiCounter;
410
411 if (secondClassificationForTaxonFlag) {
412 c++;
413 }
414
415 // run the following loop once, if this taxon only belongs to
416 // one
417 // classification.
418 // twice, if it is attached to 2 classifications
419 for (int i = classiCounter; i <= c; i++) {
420
421 // count everything just created for this taxon:
422 increment(no_of_accepted_taxa_c, i);
423 increment(no_of_taxon_names_c, i);
424 if (tNomRefFlag) {
425 increment(no_of_nomenclatural_references_c, i);
426 }
427 if (sNomRefFlag) {
428 increment(no_of_nomenclatural_references_c, i);
429 }
430 if (synonymFlag) {
431 increment(no_of_synonyms_c, i);
432 increment(no_of_taxon_names_c, i);
433 }
434 if (taxonCounter % 2 != 0) {
435 increment(no_of_all_references_c, i);
436 if (synonymFlag) {
437 increment(no_of_all_references_c, i);
438 }
439 }
440 if (tDescrSourceRefFlag) {
441 increment(no_of_descriptive_source_references_c, i,
442 descriptiveElementsPerTaxon + 2);
443 }
444
445 if (sDescrSourceRefFlag) {
446 increment(no_of_descriptive_source_references_c, i, 2);
447 }
448 }
449 // put flags back:
450 secondClassificationForTaxonFlag = false;
451 tNomRefFlag = false;
452 sNomRefFlag = false;
453 synonymFlag = false;
454 tDescrSourceRefFlag = false;
455 sDescrSourceRefFlag = false;
456 }
457
458 // modify variables (post-loop)
459 classiCounter++;
460 remainder -= taxaInClass;
461
462 }
463 merge(no_of_accepted_taxa_c, no_of_synonyms_c, no_of_all_taxa_c);
464 merge(no_of_all_references_c, no_of_nomenclatural_references_c,
465 no_of_all_references_c);
466
467 // TODO Auto-generated method stub
468
469 }
470
471 /**
472 * create and count a new sec Reference
473 *
474 * @param classiCounter
475 * @param taxonCounter
476 * @return
477 */
478 private Reference createSecReference(int classiCounter, int taxonCounter) {
479 Reference sec;
480 sec = ReferenceFactory.newBook();
481 sec.setTitle("book " + classiCounter + "." + taxonCounter);
482 referenceDao.save(sec);
483 no_of_all_references++;
484 return sec;
485 }
486
487 /**
488 * @param no_of_sth
489 * @param inClassification
490 * @param increase
491 */
492 private void increment(List<Long> no_of_sth, int inClassification,
493 int increase) {
494 no_of_sth.set(inClassification, (no_of_sth.get(inClassification))
495 + increase);
496 }
497
498 private void increment(List<Long> no_of_sth, int inClassification) {
499 increment(no_of_sth, inClassification, 1);
500 }
501
502 private void merge(List<Long> no_of_sth1, List<Long> no_of_sth2,
503 List<Long> no_of_sum) {
504
505 for (int i = 0; i < NO_OF_CLASSIFICATIONS; i++) {
506 Long sum = no_of_sth1.get(i) + no_of_sth2.get(i);
507 no_of_sum.set(i, sum);
508
509 }
510 }
511
512 private TaxonNode createTaxTree(Classification classification) {
513 Random rand = new Random();
514
515 Set<TaxonNode> nodes = classification.getAllNodes();
516 ArrayList<TaxonNode> children = new ArrayList<TaxonNode>();
517 TaxonNode parent = nodes.iterator().next();
518
519 TaxonNode root = parent;
520 nodes.remove(parent);
521 while (!nodes.isEmpty()) {
522 int n = rand.nextInt(2) + 1;
523 for (int i = 1; i <= n && !(nodes.isEmpty()); i++) {
524 TaxonNode nextNode = nodes.iterator().next();
525 parent.getChildNodes().add(nextNode);
526 children.add(nextNode);
527 nodes.remove(nextNode);
528 }
529 taxonNodeDao.save(parent);
530 parent = children.get(0);
531 children.remove(0);
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 }