1 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.statistics
;
3 import static org
.junit
.Assert
.assertTrue
;
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
;
12 import java
.util
.Random
;
14 import java
.util
.UUID
;
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
;
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
;
50 public class StatisticsDaoHibernateImplTest
51 extends CdmTransactionalIntegrationTest
{
53 @SuppressWarnings("unused")
54 private static final Logger logger
= Logger
.getLogger(StatisticsDaoHibernateImplTest
.class);
56 private static final boolean PRINTOUT
= true;
59 private IStatisticsDao statisticsDao
;
61 private UUID nodeUuid
;
63 private List
<Classification
> classifications
;
68 private static final int NO_OF_ACCEPTED_TAXA
= 10;
70 // choose a number (less than NO_OF_ACCEPTED_TAXA)
71 private static final int NO_OF_CLASSIFICATIONS
= 3;
73 // must be less or equal to NO_OF_ACCEPTED_TAXA
74 private static final int NO_OF_SYNONYMS
= 7;
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;
80 // must be NO_OF_ACCEPTED_TAXA + NO_OF_SYNONYMS
81 private static final int NO_OF_ALLTAXA
= NO_OF_ACCEPTED_TAXA
84 // must be NO_OF_ACCEPTED_TAXA+NO_OF_SYNONYMS
85 private static final int NO_OF_TAXON_NAMES
= NO_OF_ACCEPTED_TAXA
88 // this represents an approx. no of the amount that will actually generated!
89 private static final int NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
= 16;
91 // private static final int NO_OF_ALL_REFERENCES = NO_OF_ACCEPTED_TAXA + 0;
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
97 // --------------------variables for all ------------------
99 private Long no_of_all_references
= new Long(0);
100 private Long no_of_descriptive_source_references
= new Long(0);
102 // ............................................
104 // log the type enum to an int constant:
105 private Map
<String
, Long
> typeMap_ALL
;
107 // ------------------ variables for CLASSIFICATIONS -----------------------
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
126 // ........................... constant map ..........................
128 private static final Map
<String
, List
<Long
>> typeCountMap_CLASSIFICATION
= new HashMap
<String
, List
<Long
>>() {
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
);
143 // ****************** services: ************************
145 private IStatisticsDao service
;
147 private IClassificationDao classificationDao
;
149 private ITaxonDao taxonDao
;
151 private IReferenceDao referenceDao
;
153 private IDescriptionDao descriptionDao
;
155 private IDescriptionElementDao descriptionElementDao
;
157 private ITaxonNodeDao taxonNodeDao
;
161 public void setUp() {
162 // nodeUuid =UUID.fromString("46cd7e78-f7d5-4c31-937b-2bc5074618c4");
163 nodeUuid
= UUID
.fromString("0b5846e5-b8d2-4ca9-ac51-099286ea4adc");
165 AuditEventContextHolder
.clearContext();
170 public void tearDown() {
171 AuditEventContextHolder
.clearContext();
176 public void testGetAllChildNodes() {
179 for (Classification classification
: classifications
) {
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("");
190 // result=statisticsDao.getAllTaxonIds(nodeUuid);
191 // statisticsDao.getAllTaxonIds();
193 // fail("Not yet implemented");
196 private void createDataSet() {
197 // create NO_OF_CLASSIFICATIONS classifications
198 classifications
= new ArrayList
<Classification
>();
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
);
206 // create all taxa, references and synonyms and attach them to one or
207 // more classifications
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;
219 // variables: counter (pre-loop)
220 int descriptiveElementsPerTaxon
= (NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
/ NO_OF_ACCEPTED_TAXA
) + 1;
223 int classiCounter
= 0, sharedClassification
= 0, synonymCounter
= 0, nomRefCounter
= 0;
225 // iterate over classifications and add taxa
226 for (/* see above */; remainder
> 0
227 && classiCounter
< NO_OF_CLASSIFICATIONS
; /* see below */) {
229 // compute no of taxa to be created in this classification
230 if (classiCounter
>= NO_OF_CLASSIFICATIONS
- 1) { // last
234 taxaInClass
= remainder
;
235 } else { // take half of left taxa for this class:
236 taxaInClass
= remainder
/ 2;
239 // iterate over amount of taxa meant to be in this classification
240 for (int taxonCounter
= 1; taxonCounter
<= taxaInClass
; taxonCounter
++) {
242 // create a String for the Name
243 RandomStringUtils
.randomAlphabetic(10);
244 String randomName
= RandomStringUtils
.randomAlphabetic(5) + " "
245 + RandomStringUtils
.randomAlphabetic(10);
247 // create a name for the taxon
248 BotanicalName name
= BotanicalName
.NewInstance(Rank
.SPECIES());
249 name
.setNameCache(randomName
, true);
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:
255 Reference nomRef
= ReferenceFactory
.newBook();
256 name
.setNomenclaturalReference(nomRef
);
257 referenceDao
.save(nomRef
);
261 // create a new sec for every other taxon
262 if (taxonCounter
% 2 != 0) {
263 sec
= createSecReference(classiCounter
, taxonCounter
);
267 Taxon taxon
= Taxon
.NewInstance(name
, sec
);
269 // create descriptions, description sources and their references
271 if (no_of_descriptive_source_references
< NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
) {
273 tDescrSourceRefFlag
= true;
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
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
);
294 // create descriptions, description sources and their
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();
304 descriptionElementSource
.setCitation(article
);
305 descriptionElement
.addSource(descriptionElementSource
);
306 taxonDescription
.addElement(descriptionElement
);
307 referenceDao
.save(article
);
308 descriptionElementDao
.save(descriptionElement
);
311 descriptionDao
.save(taxonDescription
);
312 taxon
.addDescription(taxonDescription
);
314 // create a Specimen for taxon with description, descr.
315 // element and referece
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);
325 // descriptionService.save(specimenDescription);
326 // taxon.add(specimen);
328 no_of_descriptive_source_references
+= descriptiveElementsPerTaxon
+ 2 + 1;
332 // add taxon to classification
333 classifications
.get(classiCounter
).addChildTaxon(taxon
, null, null);
335 // now if there are any left, we create a synonym for the taxon
336 if (synonymCounter
< NO_OF_SYNONYMS
) {
338 randomName
= RandomStringUtils
.randomAlphabetic(5) + " "
339 + RandomStringUtils
.randomAlphabetic(10);
341 name
= BotanicalName
.NewInstance(Rank
.SPECIES());
342 name
.setNameCache(randomName
, true);
344 // create nomenclatural reference for synonym name (if left)
345 if (nomRefCounter
< NO_OF_NOMENCLATURAL_REFERENCES
) {
347 Reference nomRef
= ReferenceFactory
.newBook();
348 name
.setNomenclaturalReference(nomRef
);
349 referenceDao
.save(nomRef
);
353 if (no_of_descriptive_source_references
< NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
) {
354 sDescrSourceRefFlag
= true;
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
,
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;
377 // create a new reference for every other synonym:
378 if (taxonCounter
% 2 != 0) {
379 sec
= createSecReference(classiCounter
, taxonCounter
);
381 Synonym synonym
= Synonym
.NewInstance(name
, sec
);
382 taxonDao
.save(synonym
);
383 taxon
.addSynonym(synonym
,
384 SynonymType
.SYNONYM_OF());
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);
396 // we remember that this taxon is attached to 2
398 secondClassificationForTaxonFlag
= true;
399 sharedClassification
++;
400 classificationDao
.saveOrUpdate(classifications
401 .get(classiCounter
+ 1));
404 taxonDao
.save(taxon
);
405 classificationDao
.saveOrUpdate(classifications
406 .get(classiCounter
));
408 // count the data created with this taxon:
409 int c
= classiCounter
;
411 if (secondClassificationForTaxonFlag
) {
415 // run the following loop once, if this taxon only belongs to
418 // twice, if it is attached to 2 classifications
419 for (int i
= classiCounter
; i
<= c
; i
++) {
421 // count everything just created for this taxon:
422 increment(no_of_accepted_taxa_c
, i
);
423 increment(no_of_taxon_names_c
, i
);
425 increment(no_of_nomenclatural_references_c
, i
);
428 increment(no_of_nomenclatural_references_c
, i
);
431 increment(no_of_synonyms_c
, i
);
432 increment(no_of_taxon_names_c
, i
);
434 if (taxonCounter
% 2 != 0) {
435 increment(no_of_all_references_c
, i
);
437 increment(no_of_all_references_c
, i
);
440 if (tDescrSourceRefFlag
) {
441 increment(no_of_descriptive_source_references_c
, i
,
442 descriptiveElementsPerTaxon
+ 2);
445 if (sDescrSourceRefFlag
) {
446 increment(no_of_descriptive_source_references_c
, i
, 2);
450 secondClassificationForTaxonFlag
= false;
454 tDescrSourceRefFlag
= false;
455 sDescrSourceRefFlag
= false;
458 // modify variables (post-loop)
460 remainder
-= taxaInClass
;
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
);
467 // TODO Auto-generated method stub
472 * create and count a new sec Reference
474 * @param classiCounter
475 * @param taxonCounter
478 private Reference
createSecReference(int classiCounter
, int taxonCounter
) {
480 sec
= ReferenceFactory
.newBook();
481 sec
.setTitle("book " + classiCounter
+ "." + taxonCounter
);
482 referenceDao
.save(sec
);
483 no_of_all_references
++;
489 * @param inClassification
492 private void increment(List
<Long
> no_of_sth
, int inClassification
,
494 no_of_sth
.set(inClassification
, (no_of_sth
.get(inClassification
))
498 private void increment(List
<Long
> no_of_sth
, int inClassification
) {
499 increment(no_of_sth
, inClassification
, 1);
502 private void merge(List
<Long
> no_of_sth1
, List
<Long
> no_of_sth2
,
503 List
<Long
> no_of_sum
) {
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
);
512 private TaxonNode
createTaxTree(Classification classification
) {
513 Random rand
= new Random();
515 Set
<TaxonNode
> nodes
= classification
.getAllNodes();
516 ArrayList
<TaxonNode
> children
= new ArrayList
<TaxonNode
>();
517 TaxonNode parent
= nodes
.iterator().next();
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
);
529 taxonNodeDao
.save(parent
);
530 parent
= children
.get(0);
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()+" ");
550 System
.out
.println();
552 if (node
.getTaxon().getName().getNomenclaturalReference() != null) {
553 System
.out
.println(" \t(Nomencl. Ref.: "
554 + node
.getTaxon().getName()
555 .getNomenclaturalReference().getId() + ")");
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()
566 System
.out
.println();
571 System
.out
.println();
572 System
.out
.println("end!");
577 * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
580 public void createTestDataSet() throws FileNotFoundException
{
581 // TODO Auto-generated method stub