1
|
package eu.etaxonomy.cdm.api.service;
|
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.List;
|
9
|
|
10
|
import org.apache.commons.lang.RandomStringUtils;
|
11
|
import org.junit.Before;
|
12
|
import org.junit.Test;
|
13
|
import org.unitils.dbunit.annotation.DataSet;
|
14
|
import org.unitils.spring.annotation.SpringBeanByType;
|
15
|
|
16
|
import eu.etaxonomy.cdm.api.service.statistics.Statistics;
|
17
|
import eu.etaxonomy.cdm.api.service.statistics.StatisticsConfigurator;
|
18
|
import eu.etaxonomy.cdm.api.service.statistics.StatisticsPartEnum;
|
19
|
import eu.etaxonomy.cdm.api.service.statistics.StatisticsTypeEnum;
|
20
|
import eu.etaxonomy.cdm.model.common.Language;
|
21
|
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
|
22
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
23
|
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
|
24
|
import eu.etaxonomy.cdm.model.description.TaxonDescription;
|
25
|
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
|
26
|
import eu.etaxonomy.cdm.model.description.TextData;
|
27
|
import eu.etaxonomy.cdm.model.name.IBotanicalName;
|
28
|
import eu.etaxonomy.cdm.model.name.Rank;
|
29
|
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
|
30
|
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
|
31
|
import eu.etaxonomy.cdm.model.reference.Reference;
|
32
|
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
|
33
|
import eu.etaxonomy.cdm.model.taxon.Classification;
|
34
|
import eu.etaxonomy.cdm.model.taxon.Synonym;
|
35
|
import eu.etaxonomy.cdm.model.taxon.SynonymType;
|
36
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
37
|
import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
|
38
|
|
39
|
public class StatisticsServiceImplTest2 extends CdmTransactionalIntegrationTest {
|
40
|
|
41
|
// ************constants to set up the expected results for all:
|
42
|
// ********************
|
43
|
|
44
|
// ............................................
|
45
|
|
46
|
// here is the list of the types that will be test counted in the
|
47
|
// parts (ALL, CLASSIFICATION)
|
48
|
private static final List<StatisticsTypeEnum> TYPES = Arrays
|
49
|
.asList(new StatisticsTypeEnum[] {
|
50
|
StatisticsTypeEnum.CLASSIFICATION,
|
51
|
StatisticsTypeEnum.ACCEPTED_TAXA,
|
52
|
StatisticsTypeEnum.ALL_TAXA,
|
53
|
StatisticsTypeEnum.ALL_REFERENCES, // this functionality
|
54
|
// for
|
55
|
// classifications is still missing for in the Statistics
|
56
|
// Service
|
57
|
StatisticsTypeEnum.SYNONYMS,
|
58
|
StatisticsTypeEnum.TAXON_NAMES,
|
59
|
StatisticsTypeEnum.NOMENCLATURAL_REFERENCES,
|
60
|
StatisticsTypeEnum.DESCRIPTIVE_SOURCE_REFERENCES });
|
61
|
|
62
|
// private static final String[] TYPES = { "CLASSIFICATION",
|
63
|
// "ACCEPTED_TAXA",
|
64
|
// "ALL_TAXA", "ALL_REFERENCES" };
|
65
|
|
66
|
// ................parts ..............................
|
67
|
|
68
|
private static final List<String> PARTS = Arrays.asList(new String[] {
|
69
|
"ALL", "CLASSIFICATION" });
|
70
|
// .........................................................
|
71
|
|
72
|
private ArrayList<Classification> classifications;
|
73
|
|
74
|
// ****************** services: ************************
|
75
|
@SpringBeanByType
|
76
|
private IStatisticsService service;
|
77
|
@SpringBeanByType
|
78
|
private IClassificationService classificationService;
|
79
|
@SpringBeanByType
|
80
|
private ITaxonService taxonService;
|
81
|
@SpringBeanByType
|
82
|
private IReferenceService referenceService;
|
83
|
@SpringBeanByType
|
84
|
private IDescriptionService descriptionService;
|
85
|
|
86
|
// ............................................
|
87
|
|
88
|
@Before
|
89
|
// @DataSet
|
90
|
public void setUp() throws Exception {
|
91
|
// createTestData(3, 10, 7, 16, 4);
|
92
|
// OutputStream out= new ByteArrayOutputStream();
|
93
|
// printDataSet(out);
|
94
|
// System.out.println(out.toString());
|
95
|
}
|
96
|
|
97
|
@Test
|
98
|
@DataSet
|
99
|
public void testGetCountStatistics() {
|
100
|
|
101
|
// create configurator needed to call
|
102
|
// StatisticsService.getCountStatistics()
|
103
|
List<StatisticsConfigurator> configuratorList = createConfiguratorList(
|
104
|
(String[]) PARTS.toArray(), TYPES);
|
105
|
|
106
|
// run method of StatisticsService
|
107
|
List<Statistics> statisticsList = service
|
108
|
.getCountStatistics(configuratorList);
|
109
|
|
110
|
// print out result
|
111
|
logger.info("statistics service result: ");
|
112
|
for (Statistics statistics : statisticsList) {
|
113
|
logger.info(statistics.getCountMap().toString());
|
114
|
}
|
115
|
|
116
|
assertTrue(true);
|
117
|
}
|
118
|
|
119
|
private List<StatisticsConfigurator> createConfiguratorList(String[] part,
|
120
|
List<StatisticsTypeEnum> types) {
|
121
|
|
122
|
ArrayList<StatisticsConfigurator> configuratorList = new ArrayList<StatisticsConfigurator>();
|
123
|
|
124
|
// 1. get types for configurators:
|
125
|
// in our case all the configurators will have the same types
|
126
|
// so we calculate the types once and save them in a helperConfigurator
|
127
|
StatisticsConfigurator helperConfigurator = new StatisticsConfigurator();
|
128
|
|
129
|
if (types != null) {
|
130
|
for (StatisticsTypeEnum type : types) {
|
131
|
helperConfigurator.addType(type);
|
132
|
}
|
133
|
} else {
|
134
|
for (StatisticsTypeEnum enumValue : StatisticsTypeEnum.values()) {
|
135
|
helperConfigurator.addType(enumValue);
|
136
|
}
|
137
|
}
|
138
|
|
139
|
// 2. determine the entities and put each of them in a configurator:
|
140
|
|
141
|
// if no part was given:
|
142
|
if (part == null) {
|
143
|
helperConfigurator.addFilter(null); // part= null means search all
|
144
|
// DB
|
145
|
configuratorList.add(helperConfigurator);
|
146
|
}
|
147
|
// else parse list of parts and create configurator for each:
|
148
|
else {
|
149
|
for (String string : part) {
|
150
|
if (string.equals(StatisticsPartEnum.ALL.toString())) {
|
151
|
helperConfigurator.addFilter(null);
|
152
|
configuratorList.add(helperConfigurator);
|
153
|
} else if (string.equals(StatisticsPartEnum.CLASSIFICATION
|
154
|
.toString())) {
|
155
|
List<Classification> classificationsList = classificationService
|
156
|
.listClassifications(null, 0, null, null);
|
157
|
for (Classification classification : classificationsList) {
|
158
|
|
159
|
StatisticsConfigurator newConfigurator = new StatisticsConfigurator();
|
160
|
newConfigurator.setType(helperConfigurator.getType());
|
161
|
newConfigurator.getFilter().addAll(
|
162
|
helperConfigurator.getFilter());
|
163
|
newConfigurator.addFilter(classification);
|
164
|
configuratorList.add(newConfigurator);
|
165
|
}
|
166
|
}
|
167
|
}
|
168
|
|
169
|
}
|
170
|
|
171
|
return configuratorList;
|
172
|
}
|
173
|
|
174
|
public void createTestDataSet(int noOfClassifications, int noOfAcceptedTaxa,
|
175
|
int noOfSynonyms, int noOfDescrSrcReferences, int sharedTaxa)
|
176
|
throws Exception {
|
177
|
|
178
|
// create more parameters:
|
179
|
int noOfNomRefs = noOfAcceptedTaxa + noOfSynonyms - 4;
|
180
|
|
181
|
// missing in this example data:
|
182
|
// synonyms, that are attached to several taxa (same or different
|
183
|
// classification)
|
184
|
|
185
|
// --------------------variables for counting produced elements
|
186
|
// ------------------
|
187
|
|
188
|
int no_of_all_references = 0;
|
189
|
int descrSrcReferencesCounter = 0;
|
190
|
|
191
|
// create noOfClassifications classifications
|
192
|
classifications = new ArrayList<Classification>();
|
193
|
|
194
|
for (int i = 1; i <= noOfClassifications; i++) {
|
195
|
Classification classification = Classification
|
196
|
.NewInstance("European Abies" + i);
|
197
|
classifications.add(classification);
|
198
|
classificationService.save(classification);
|
199
|
|
200
|
}
|
201
|
// create all taxa, references and synonyms and attach them to one or
|
202
|
// more classifications
|
203
|
|
204
|
// variables: flags
|
205
|
int remainder = noOfAcceptedTaxa;
|
206
|
Reference sec = ReferenceFactory.newBook();
|
207
|
boolean secondClassificationForTaxonFlag = false;
|
208
|
boolean synonymFlag = false;
|
209
|
boolean tNomRefFlag = false;
|
210
|
boolean sNomRefFlag = false;
|
211
|
boolean tDescrSourceRefFlag = false;
|
212
|
boolean sDescrSourceRefFlag = false;
|
213
|
|
214
|
// variables: counter (pre-loop)
|
215
|
int descriptiveElementsPerTaxon = (noOfDescrSrcReferences / noOfAcceptedTaxa) + 1;
|
216
|
|
217
|
int taxaInClass;
|
218
|
int classiCounter = 0, sharedClassification = 0, synonymCounter = 0, nomRefCounter = 0;
|
219
|
|
220
|
// iterate over classifications and add taxa
|
221
|
for (/* see above */; remainder > 0
|
222
|
&& classiCounter < noOfClassifications; /* see below */) {
|
223
|
|
224
|
// compute no of taxa to be created in this classification
|
225
|
if (classiCounter >= noOfClassifications - 1) { // last
|
226
|
// classification
|
227
|
// gets all left
|
228
|
// taxa
|
229
|
taxaInClass = remainder;
|
230
|
} else { // take half of left taxa for this class:
|
231
|
taxaInClass = remainder / 2;
|
232
|
}
|
233
|
|
234
|
// iterate over amount of taxa meant to be in this classification
|
235
|
for (int taxonCounter = 1; taxonCounter <= taxaInClass; taxonCounter++) {
|
236
|
|
237
|
// create a String for the Name
|
238
|
RandomStringUtils.randomAlphabetic(10);
|
239
|
String randomName = RandomStringUtils.randomAlphabetic(5) + " "
|
240
|
+ RandomStringUtils.randomAlphabetic(10);
|
241
|
|
242
|
// create a name for the taxon
|
243
|
IBotanicalName name = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
|
244
|
name.setNameCache(randomName, true);
|
245
|
|
246
|
// create nomenclatural reference for taxon name (if left)
|
247
|
if (nomRefCounter < noOfNomRefs) {
|
248
|
// we remember this taxon has a nomenclatural reference:
|
249
|
tNomRefFlag = true;
|
250
|
Reference nomRef = ReferenceFactory.newBook();
|
251
|
name.setNomenclaturalReference(nomRef);
|
252
|
referenceService.save(nomRef);
|
253
|
nomRefCounter++;
|
254
|
}
|
255
|
|
256
|
// create a new sec for every other taxon
|
257
|
if (taxonCounter % 2 != 0) {
|
258
|
sec = createSecReference(classiCounter, taxonCounter);
|
259
|
}
|
260
|
|
261
|
// create the taxon
|
262
|
Taxon taxon = Taxon.NewInstance(name, sec);
|
263
|
|
264
|
// create descriptions, description sources and their references
|
265
|
|
266
|
if (descrSrcReferencesCounter < noOfDescrSrcReferences) {
|
267
|
|
268
|
tDescrSourceRefFlag = true;
|
269
|
|
270
|
// create a description and 2 description elements with
|
271
|
// references for taxon name
|
272
|
TaxonNameDescription nameDescr = TaxonNameDescription
|
273
|
.NewInstance();
|
274
|
CommonTaxonName nameElement = CommonTaxonName.NewInstance(
|
275
|
"Veilchen" + taxonCounter, Language.GERMAN());
|
276
|
TextData textElement = new TextData();
|
277
|
Reference nameElementRef = ReferenceFactory.newArticle();
|
278
|
Reference textElementRef = ReferenceFactory
|
279
|
.newBookSection();
|
280
|
nameElement.addSource(
|
281
|
OriginalSourceType.PrimaryTaxonomicSource, null,
|
282
|
null, nameElementRef, "name: ");
|
283
|
textElement.addSource(
|
284
|
OriginalSourceType.PrimaryTaxonomicSource, null,
|
285
|
null, textElementRef, "text: ");
|
286
|
nameDescr.addElement(nameElement);
|
287
|
nameDescr.addElement(textElement);
|
288
|
name.addDescription(nameDescr);
|
289
|
// taxon.getName().addDescription(nameDescr);
|
290
|
referenceService.save(nameElementRef);
|
291
|
referenceService.save(textElementRef);
|
292
|
descriptionService.save(nameDescr);
|
293
|
System.out.println("Descriptive Src Ref for TaxonName: "+nameElementRef.getId()+" Taxon: "+taxon.getId()+" name: "+taxon.getTitleCache());
|
294
|
System.out.println("Descriptive Src Ref for TaxonName: "+textElementRef.getId()+" Taxon: "+taxon.getId()+" name: "+taxon.getTitleCache());
|
295
|
|
296
|
// ###
|
297
|
// create descriptions, description sources and their
|
298
|
// references
|
299
|
// for taxon
|
300
|
TaxonDescription taxonDescription = new TaxonDescription();
|
301
|
for (int i = 0; i < descriptiveElementsPerTaxon; i++) {
|
302
|
DescriptionElementBase descriptionElement = new TextData();
|
303
|
DescriptionElementSource descriptionElementSource = DescriptionElementSource
|
304
|
.NewInstance(OriginalSourceType.PrimaryTaxonomicSource);
|
305
|
Reference article = ReferenceFactory.newArticle();
|
306
|
|
307
|
descriptionElementSource.setCitation(article);
|
308
|
descriptionElement.addSource(descriptionElementSource);
|
309
|
taxonDescription.addElement(descriptionElement);
|
310
|
referenceService.save(article);
|
311
|
descriptionService
|
312
|
.saveDescriptionElement(descriptionElement);
|
313
|
System.out.println("Descriptive Src Ref for Taxon: "+article.getId()+" Taxon: "+taxon.getId()+" name: "+taxon.getTitleCache());
|
314
|
|
315
|
}
|
316
|
descriptionService.save(taxonDescription);
|
317
|
taxon.addDescription(taxonDescription);
|
318
|
|
319
|
//TODO create Sspecimen connected to taxon via TaxonDescription->DescriptionElement=IndividualAssoziation->setAssociatedSpecimenOrObservation(SpecimenOrObservationBase)
|
320
|
// TODO and NameBase->SpecimenTypeDesignation->
|
321
|
// DerrivedUnit???
|
322
|
|
323
|
// create a Specimen for taxon with description, descr.
|
324
|
// element and referece
|
325
|
//
|
326
|
// SpecimenOrObservationBase specimen = DerivedUnit.NewInstance(SpecimenOrObservationType.Fossil);
|
327
|
// SpecimenDescription specimenDescription =
|
328
|
// SpecimenDescription.NewInstance(specimen);
|
329
|
// DescriptionElementBase descrElement = new TextData();
|
330
|
// Reference specimenRef = ReferenceFactory.newArticle();
|
331
|
//// descrElement.add;
|
332
|
//
|
333
|
//
|
334
|
// descriptionService.save(specimenDescription);
|
335
|
// taxon.addSource(
|
336
|
// OriginalSourceType.PrimaryTaxonomicSource,
|
337
|
// null, null, nameElementRef, " ");
|
338
|
// taxon.add(specimen);
|
339
|
|
340
|
descrSrcReferencesCounter += descriptiveElementsPerTaxon + 2 + 1;
|
341
|
|
342
|
}
|
343
|
|
344
|
// add taxon to classification
|
345
|
classifications.get(classiCounter).addChildTaxon(taxon, null,
|
346
|
null);
|
347
|
|
348
|
// now if there are any left, we create a synonym for the taxon
|
349
|
if (synonymCounter < noOfSynonyms) {
|
350
|
synonymFlag = true;
|
351
|
randomName = RandomStringUtils.randomAlphabetic(5) + " "
|
352
|
+ RandomStringUtils.randomAlphabetic(10);
|
353
|
// name for synonym
|
354
|
name = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
|
355
|
name.setNameCache(randomName, true);
|
356
|
|
357
|
// create nomenclatural reference for synonym name (if left)
|
358
|
if (nomRefCounter < noOfNomRefs) {
|
359
|
sNomRefFlag = true;
|
360
|
Reference nomRef = ReferenceFactory.newBook();
|
361
|
name.setNomenclaturalReference(nomRef);
|
362
|
referenceService.save(nomRef);
|
363
|
nomRefCounter++;
|
364
|
}
|
365
|
|
366
|
if (descrSrcReferencesCounter < noOfDescrSrcReferences) {
|
367
|
sDescrSourceRefFlag = true;
|
368
|
|
369
|
// create a description and 2 description elements with
|
370
|
// references for synonym name
|
371
|
TaxonNameDescription nameDescr = TaxonNameDescription
|
372
|
.NewInstance();
|
373
|
CommonTaxonName nameElement = CommonTaxonName
|
374
|
.NewInstance("anderes Veilchen" + taxonCounter,
|
375
|
Language.GERMAN());
|
376
|
TextData textElement = new TextData();
|
377
|
Reference nameElementRef = ReferenceFactory
|
378
|
.newArticle();
|
379
|
Reference textElementRef = ReferenceFactory
|
380
|
.newBookSection();
|
381
|
nameElement.addSource(
|
382
|
OriginalSourceType.PrimaryTaxonomicSource,
|
383
|
null, null, nameElementRef, "name: ");
|
384
|
textElement.addSource(
|
385
|
OriginalSourceType.PrimaryTaxonomicSource,
|
386
|
null, null, textElementRef, "text: ");
|
387
|
nameDescr.addElement(nameElement);
|
388
|
nameDescr.addElement(textElement);
|
389
|
name.addDescription(nameDescr);
|
390
|
// taxon.getName().addDescription(nameDescr);
|
391
|
referenceService.save(nameElementRef);
|
392
|
referenceService.save(textElementRef);
|
393
|
descriptionService.save(nameDescr);
|
394
|
descrSrcReferencesCounter += 2;
|
395
|
System.out.println("Descriptive Src Ref for Synonym: "+nameElementRef.getId()+" Taxon: "+taxon.getId()+" name: "+taxon.getTitleCache());
|
396
|
System.out.println("Descriptive Src Ref for Synonym: "+textElementRef.getId()+" Taxon: "+taxon.getId()+" name: "+taxon.getTitleCache());
|
397
|
}
|
398
|
|
399
|
// create a new reference for every other synonym:
|
400
|
if (taxonCounter % 2 != 0) {
|
401
|
sec = createSecReference(classiCounter, taxonCounter);
|
402
|
}
|
403
|
Synonym synonym = Synonym.NewInstance(name, sec);
|
404
|
taxonService.save(synonym);
|
405
|
taxon.addSynonym(synonym,
|
406
|
SynonymType.SYNONYM_OF());
|
407
|
|
408
|
synonymCounter++;
|
409
|
}
|
410
|
|
411
|
// if this is not the last classification and there are
|
412
|
// taxa left that should be in more than one classification
|
413
|
// we add the taxon to the next class in the list too.
|
414
|
|
415
|
if (classiCounter < noOfClassifications
|
416
|
&& sharedClassification < sharedTaxa) {
|
417
|
classifications.get(classiCounter + 1).addChildTaxon(taxon,
|
418
|
null, null);
|
419
|
|
420
|
// we remember that this taxon is attached to 2
|
421
|
// classifications:
|
422
|
secondClassificationForTaxonFlag = true;
|
423
|
sharedClassification++;
|
424
|
classificationService.saveOrUpdate(classifications
|
425
|
.get(classiCounter + 1));
|
426
|
|
427
|
}
|
428
|
|
429
|
taxonService.save(taxon);
|
430
|
classificationService.saveOrUpdate(classifications
|
431
|
.get(classiCounter));
|
432
|
|
433
|
// count the data created with this taxon:
|
434
|
int c = classiCounter;
|
435
|
|
436
|
if (secondClassificationForTaxonFlag) {
|
437
|
c++;
|
438
|
}
|
439
|
|
440
|
// put flags back:
|
441
|
secondClassificationForTaxonFlag = false;
|
442
|
tNomRefFlag = false;
|
443
|
sNomRefFlag = false;
|
444
|
synonymFlag = false;
|
445
|
tDescrSourceRefFlag = false;
|
446
|
sDescrSourceRefFlag = false;
|
447
|
}
|
448
|
|
449
|
// modify variables (post-loop)
|
450
|
classiCounter++;
|
451
|
remainder -= taxaInClass;
|
452
|
|
453
|
}
|
454
|
|
455
|
commit();
|
456
|
|
457
|
writeDbUnitDataSetFile(new String[] { "TAXONBASE", "TAXONNAME",
|
458
|
"TAXONRELATIONSHIP", "REFERENCE",
|
459
|
"DESCRIPTIONELEMENTBASE",
|
460
|
"DESCRIPTIONELEMENTBASE_ORIGINALSOURCEBASE",
|
461
|
"ORIGINALSOURCEBASE", "DESCRIPTIONBASE", "REFERENCE_ORIGINALSOURCEBASE","LANGUAGESTRING",
|
462
|
"CLASSIFICATION", "TAXONNODE",
|
463
|
"HIBERNATE_SEQUENCES" });
|
464
|
|
465
|
// "AGENTBASE","HOMOTYPICALGROUP","LANGUAGESTRING",
|
466
|
// "DESCRIPTIONELEMENTBASE_LANGUAGESTRING", "HIBERNATE_SEQUENCES"
|
467
|
}
|
468
|
|
469
|
/**
|
470
|
* create and count a new sec Reference
|
471
|
*
|
472
|
* @param classiCounter
|
473
|
* @param taxonCounter
|
474
|
* @return
|
475
|
*/
|
476
|
private Reference createSecReference(int classiCounter, int taxonCounter) {
|
477
|
Reference sec;
|
478
|
sec = ReferenceFactory.newBook();
|
479
|
sec.setTitle("book " + classiCounter + "." + taxonCounter);
|
480
|
referenceService.save(sec);
|
481
|
return sec;
|
482
|
}
|
483
|
|
484
|
/* (non-Javadoc)
|
485
|
* @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
|
486
|
*/
|
487
|
@Override
|
488
|
public void createTestDataSet() throws FileNotFoundException {
|
489
|
// TODO Auto-generated method stub
|
490
|
|
491
|
}
|
492
|
|
493
|
}
|