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
);
183 result
=statisticsDao
.getAllChildNodeIds(root
.getUuid());
184 System
.out
.println("classification "+ classification
.getName()+": ");
185 System
.out
.println("result: "+result
.toString());
186 System
.out
.println("");
191 // result=statisticsDao.getAllTaxonIds(nodeUuid);
192 // statisticsDao.getAllTaxonIds();
194 // fail("Not yet implemented");
197 private void createDataSet() {
198 // create NO_OF_CLASSIFICATIONS classifications
199 classifications
= new ArrayList
<Classification
>();
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
);
207 // create all taxa, references and synonyms and attach them to one or
208 // more classifications
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;
220 // variables: counter (pre-loop)
221 int descriptiveElementsPerTaxon
= (NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
/ NO_OF_ACCEPTED_TAXA
) + 1;
224 int classiCounter
= 0, sharedClassification
= 0, synonymCounter
= 0, nomRefCounter
= 0;
226 // iterate over classifications and add taxa
227 for (/* see above */; remainder
> 0
228 && classiCounter
< NO_OF_CLASSIFICATIONS
; /* see below */) {
230 // compute no of taxa to be created in this classification
231 if (classiCounter
>= NO_OF_CLASSIFICATIONS
- 1) { // last
235 taxaInClass
= remainder
;
236 } else { // take half of left taxa for this class:
237 taxaInClass
= remainder
/ 2;
240 // iterate over amount of taxa meant to be in this classification
241 for (int taxonCounter
= 1; taxonCounter
<= taxaInClass
; taxonCounter
++) {
243 // create a String for the Name
244 RandomStringUtils
.randomAlphabetic(10);
245 String randomName
= RandomStringUtils
.randomAlphabetic(5) + " "
246 + RandomStringUtils
.randomAlphabetic(10);
248 // create a name for the taxon
249 BotanicalName name
= BotanicalName
.NewInstance(Rank
.SPECIES());
250 name
.setNameCache(randomName
, true);
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:
256 Reference nomRef
= ReferenceFactory
.newBook();
257 name
.setNomenclaturalReference(nomRef
);
258 referenceDao
.save(nomRef
);
262 // create a new sec for every other taxon
263 if (taxonCounter
% 2 != 0) {
264 sec
= createSecReference(classiCounter
, taxonCounter
);
268 Taxon taxon
= Taxon
.NewInstance(name
, sec
);
270 // create descriptions, description sources and their references
272 if (no_of_descriptive_source_references
< NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
) {
274 tDescrSourceRefFlag
= true;
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
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
);
295 // create descriptions, description sources and their
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();
305 descriptionElementSource
.setCitation(article
);
306 descriptionElement
.addSource(descriptionElementSource
);
307 taxonDescription
.addElement(descriptionElement
);
308 referenceDao
.save(article
);
309 descriptionElementDao
.save(descriptionElement
);
312 descriptionDao
.save(taxonDescription
);
313 taxon
.addDescription(taxonDescription
);
315 // create a Specimen for taxon with description, descr.
316 // element and referece
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);
326 // descriptionService.save(specimenDescription);
327 // taxon.add(specimen);
329 no_of_descriptive_source_references
+= descriptiveElementsPerTaxon
+ 2 + 1;
333 // add taxon to classification
334 classifications
.get(classiCounter
).addChildTaxon(taxon
, null, null);
336 // now if there are any left, we create a synonym for the taxon
337 if (synonymCounter
< NO_OF_SYNONYMS
) {
339 randomName
= RandomStringUtils
.randomAlphabetic(5) + " "
340 + RandomStringUtils
.randomAlphabetic(10);
342 name
= BotanicalName
.NewInstance(Rank
.SPECIES());
343 name
.setNameCache(randomName
, true);
345 // create nomenclatural reference for synonym name (if left)
346 if (nomRefCounter
< NO_OF_NOMENCLATURAL_REFERENCES
) {
348 Reference nomRef
= ReferenceFactory
.newBook();
349 name
.setNomenclaturalReference(nomRef
);
350 referenceDao
.save(nomRef
);
354 if (no_of_descriptive_source_references
< NO_OF_DESCRIPTIVE_SOURCE_REFERENCES
) {
355 sDescrSourceRefFlag
= true;
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
,
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;
378 // create a new reference for every other synonym:
379 if (taxonCounter
% 2 != 0) {
380 sec
= createSecReference(classiCounter
, taxonCounter
);
382 Synonym synonym
= Synonym
.NewInstance(name
, sec
);
383 taxonDao
.save(synonym
);
384 taxon
.addSynonym(synonym
,
385 SynonymType
.SYNONYM_OF());
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);
397 // we remember that this taxon is attached to 2
399 secondClassificationForTaxonFlag
= true;
400 sharedClassification
++;
401 classificationDao
.saveOrUpdate(classifications
402 .get(classiCounter
+ 1));
405 taxonDao
.save(taxon
);
406 classificationDao
.saveOrUpdate(classifications
407 .get(classiCounter
));
409 // count the data created with this taxon:
410 int c
= classiCounter
;
412 if (secondClassificationForTaxonFlag
) {
416 // run the following loop once, if this taxon only belongs to
419 // twice, if it is attached to 2 classifications
420 for (int i
= classiCounter
; i
<= c
; i
++) {
422 // count everything just created for this taxon:
423 increment(no_of_accepted_taxa_c
, i
);
424 increment(no_of_taxon_names_c
, i
);
426 increment(no_of_nomenclatural_references_c
, i
);
429 increment(no_of_nomenclatural_references_c
, i
);
432 increment(no_of_synonyms_c
, i
);
433 increment(no_of_taxon_names_c
, i
);
435 if (taxonCounter
% 2 != 0) {
436 increment(no_of_all_references_c
, i
);
438 increment(no_of_all_references_c
, i
);
441 if (tDescrSourceRefFlag
) {
442 increment(no_of_descriptive_source_references_c
, i
,
443 descriptiveElementsPerTaxon
+ 2);
446 if (sDescrSourceRefFlag
) {
447 increment(no_of_descriptive_source_references_c
, i
, 2);
451 secondClassificationForTaxonFlag
= false;
455 tDescrSourceRefFlag
= false;
456 sDescrSourceRefFlag
= false;
459 // modify variables (post-loop)
461 remainder
-= taxaInClass
;
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
);
468 // TODO Auto-generated method stub
473 * create and count a new sec Reference
475 * @param classiCounter
476 * @param taxonCounter
479 private Reference
createSecReference(int classiCounter
, int taxonCounter
) {
481 sec
= ReferenceFactory
.newBook();
482 sec
.setTitle("book " + classiCounter
+ "." + taxonCounter
);
483 referenceDao
.save(sec
);
484 no_of_all_references
++;
490 * @param inClassification
493 private void increment(List
<Long
> no_of_sth
, int inClassification
,
495 no_of_sth
.set(inClassification
, (no_of_sth
.get(inClassification
))
499 private void increment(List
<Long
> no_of_sth
, int inClassification
) {
500 increment(no_of_sth
, inClassification
, 1);
503 private void merge(List
<Long
> no_of_sth1
, List
<Long
> no_of_sth2
,
504 List
<Long
> no_of_sum
) {
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
);
513 private TaxonNode
createTaxTree(Classification classification
) {
514 Random rand
= new Random();
516 Set
<TaxonNode
> nodes
= classification
.getAllNodes();
517 ArrayList
<TaxonNode
> children
= new ArrayList
<>();
518 TaxonNode parent
= nodes
.iterator().next();
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
);
531 parent
= children
.get(0);
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()+" ");
552 System
.out
.println();
554 if (node
.getTaxon().getName().getNomenclaturalReference() != null) {
555 System
.out
.println(" \t(Nomencl. Ref.: "
556 + node
.getTaxon().getName()
557 .getNomenclaturalReference().getId() + ")");
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()
568 System
.out
.println();
573 System
.out
.println();
574 System
.out
.println("end!");
579 * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
582 public void createTestDataSet() throws FileNotFoundException
{
583 // TODO Auto-generated method stub