un-commenting test part
[cdmlib.git] / cdmlib-services / src / test / java / eu / etaxonomy / cdm / api / service / TaxonServiceSearchTest.java
1 /**
2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.api.service;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14
15 import java.io.FileNotFoundException;
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.EnumSet;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.UUID;
25
26 import org.apache.commons.lang.RandomStringUtils;
27 import org.apache.log4j.Level;
28 import org.apache.log4j.Logger;
29 import org.apache.lucene.document.Document;
30 import org.apache.lucene.index.CorruptIndexException;
31 import org.apache.lucene.queryparser.classic.ParseException;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Ignore;
35 import org.junit.Test;
36 import org.unitils.dbunit.annotation.DataSet;
37 import org.unitils.spring.annotation.SpringBeanByType;
38
39 import eu.etaxonomy.cdm.api.service.config.FindTaxaAndNamesConfiguratorImpl;
40 import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;
41 import eu.etaxonomy.cdm.api.service.pager.Pager;
42 import eu.etaxonomy.cdm.api.service.search.ICdmMassIndexer;
43 import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearchException;
44 import eu.etaxonomy.cdm.api.service.search.SearchResult;
45 import eu.etaxonomy.cdm.common.UTF8;
46 import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor;
47 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
48 import eu.etaxonomy.cdm.model.common.CdmBase;
49 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
50 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
51 import eu.etaxonomy.cdm.model.common.Language;
52 import eu.etaxonomy.cdm.model.description.CategoricalData;
53 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
54 import eu.etaxonomy.cdm.model.description.DescriptionBase;
55 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
56 import eu.etaxonomy.cdm.model.description.Distribution;
57 import eu.etaxonomy.cdm.model.description.Feature;
58 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
59 import eu.etaxonomy.cdm.model.description.State;
60 import eu.etaxonomy.cdm.model.description.StateData;
61 import eu.etaxonomy.cdm.model.description.TaxonDescription;
62 import eu.etaxonomy.cdm.model.description.TextData;
63 import eu.etaxonomy.cdm.model.location.Country;
64 import eu.etaxonomy.cdm.model.location.NamedArea;
65 import eu.etaxonomy.cdm.model.name.BotanicalName;
66 import eu.etaxonomy.cdm.model.name.NonViralName;
67 import eu.etaxonomy.cdm.model.name.Rank;
68 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
69 import eu.etaxonomy.cdm.model.reference.Reference;
70 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
71 import eu.etaxonomy.cdm.model.taxon.Classification;
72 import eu.etaxonomy.cdm.model.taxon.Synonym;
73 import eu.etaxonomy.cdm.model.taxon.SynonymType;
74 import eu.etaxonomy.cdm.model.taxon.Taxon;
75 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
76 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
77 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
78 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
79 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
80 import eu.etaxonomy.cdm.persistence.query.MatchMode;
81 import eu.etaxonomy.cdm.persistence.query.OrderHint;
82 import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
83 import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
84
85 /**
86 * @author a.babadshanjan, a.kohlbecker
87 * @created 04.02.2009
88 */
89 public class TaxonServiceSearchTest extends CdmTransactionalIntegrationTest {
90
91 private static final String ABIES_BALSAMEA_UUID = "f65d47bd-4f49-4ab1-bc4a-bc4551eaa1a8";
92
93 private static final String ABIES_ALBA_UUID = "7dbd5810-a3e5-44b6-b563-25152b8867f4";
94
95 private static final String CLASSIFICATION_UUID = "2a5ceebb-4830-4524-b330-78461bf8cb6b";
96
97 private static final String CLASSIFICATION_ALT_UUID = "d7c741e3-ae9e-4a7d-a566-9e3a7a0b51ce";
98
99 private static final String D_ABIES_BALSAMEA_UUID = "900108d8-e6ce-495e-b32e-7aad3099135e";
100
101 private static final String D_ABIES_ALBA_UUID = "ec8bba03-d993-4c85-8472-18b14942464b";
102
103 private static final String D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID = "e9d8c2fd-6409-46d5-9c2e-14a2bbb1b2b1";
104 private static final int NUM_OF_NEW_RADOM_ENTITIES = 1000;
105
106 private static Logger logger = Logger.getLogger(TaxonServiceSearchTest.class);
107
108
109
110 @SpringBeanByType
111 private ITaxonService taxonService;
112 @SpringBeanByType
113 private ITermService termService;
114 @SpringBeanByType
115 private IClassificationService classificationService;
116 @SpringBeanByType
117 private IReferenceService referenceService;
118 @SpringBeanByType
119 private IDescriptionService descriptionService;
120 @SpringBeanByType
121 private INameService nameService;
122 @SpringBeanByType
123 private ICdmMassIndexer indexer;
124
125 @SpringBeanByType
126 private ITaxonNodeService nodeService;
127
128 private static final int BENCHMARK_ROUNDS = 300;
129
130 private Set<Class<? extends CdmBase>> typesToIndex = null;
131
132 private NamedArea germany;
133 private NamedArea france ;
134 private NamedArea russia ;
135 private NamedArea canada ;
136
137 /**
138 * @throws java.lang.Exception
139 */
140 @Before
141 public void setUp() throws Exception {
142 typesToIndex = new HashSet<Class<? extends CdmBase>>();
143 typesToIndex.add(DescriptionElementBase.class);
144 typesToIndex.add(TaxonBase.class);
145 typesToIndex.add(TaxonRelationship.class);
146
147 germany = Country.GERMANY();
148 france = Country.FRANCEFRENCHREPUBLIC();
149 russia = Country.RUSSIANFEDERATION();
150 canada = Country.CANADA();
151
152
153 }
154
155 @Test
156 public void testDbUnitUsageTest() throws Exception {
157 assertNotNull("taxonService should exist", taxonService);
158 assertNotNull("nameService should exist", nameService);
159 }
160
161 /**
162 * Test method for
163 * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator)}
164 * .
165 */
166 @Test
167 @DataSet
168 public final void testFindTaxaAndNames() {
169
170 // pass 1
171 IFindTaxaAndNamesConfigurator<?> configurator = new FindTaxaAndNamesConfiguratorImpl();
172 configurator.setTitleSearchString("Abies*");
173 configurator.setMatchMode(MatchMode.BEGINNING);
174 configurator.setDoTaxa(true);
175 configurator.setDoSynonyms(true);
176 configurator.setDoNamesWithoutTaxa(true);
177 configurator.setDoTaxaByCommonNames(true);
178
179 Pager<IdentifiableEntity> pager = taxonService.findTaxaAndNames(configurator);
180 List<IdentifiableEntity> list = pager.getRecords();
181
182 if (logger.isDebugEnabled()) {
183 for (int i = 0; i < list.size(); i++) {
184 String nameCache = "";
185 if (list.get(i) instanceof NonViralName) {
186 nameCache = ((NonViralName<?>) list.get(i)).getNameCache();
187 } else if (list.get(i) instanceof TaxonBase) {
188 TaxonNameBase<?,?> taxonNameBase = ((TaxonBase) list.get(i)).getName();
189 nameCache = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class).getNameCache();
190 } else {
191 }
192 logger.debug(list.get(i).getClass() + "(" + i + ")" + ": Name Cache = " + nameCache + ", Title Cache = "
193 + list.get(i).getTitleCache());
194 }
195 }
196
197 logger.debug("number of taxa: " + list.size());
198 assertEquals(10, list.size());
199 configurator.setTitleSearchString("Balsam-Tanne");
200 pager = taxonService.findTaxaAndNames(configurator);
201 list = pager.getRecords();
202 assertEquals(1, list.size());
203 // pass 2
204 configurator.setDoTaxaByCommonNames(false);
205 configurator.setDoMisappliedNames(true);
206 configurator.setClassification(classificationService.load(UUID.fromString(CLASSIFICATION_UUID)));
207 pager = taxonService.findTaxaAndNames(configurator);
208 list = pager.getRecords();
209 assertEquals(0, list.size());
210
211 }
212
213 /**
214 * Test method for
215 * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator)}
216 * .
217 */
218 @Test
219 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
220 public final void testFindTaxaAndNamesWithHybridFormula() {
221
222 // pass 1
223 IFindTaxaAndNamesConfigurator<?> configurator = new FindTaxaAndNamesConfiguratorImpl();
224 configurator.setTitleSearchString("Achillea*");
225 configurator.setMatchMode(MatchMode.BEGINNING);
226 configurator.setDoTaxa(true);
227 configurator.setDoSynonyms(true);
228 configurator.setDoNamesWithoutTaxa(true);
229 configurator.setDoTaxaByCommonNames(true);
230
231 Pager<IdentifiableEntity> pager = taxonService.findTaxaAndNames(configurator);
232 // Assert.assertEquals("Expecting one taxon",1,pager.getRecords().size());
233 List<IdentifiableEntity> list = pager.getRecords();
234 }
235
236 /**
237 * Test method for
238 * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#searchTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.Reference)}
239 * .
240 */
241 @Test
242 @DataSet
243 public final void testSearchTaxaByName() {
244 IFindTaxaAndNamesConfigurator<?> configurator = new FindTaxaAndNamesConfiguratorImpl();
245 configurator.setTitleSearchString("Abies bor*");
246 configurator.setMatchMode(MatchMode.BEGINNING);
247 configurator.setDoTaxa(true);
248 configurator.setDoSynonyms(false);
249 configurator.setDoNamesWithoutTaxa(true);
250 configurator.setDoTaxaByCommonNames(false);
251
252 List<UuidAndTitleCache<IdentifiableEntity>> list = taxonService.findTaxaAndNamesForEditor(configurator);
253
254 Assert.assertEquals("Expecting one entity", 1, list.size());
255
256 configurator.setTitleSearchString("silver fir");
257 configurator.setMatchMode(MatchMode.BEGINNING);
258 configurator.setDoTaxa(false);
259 configurator.setDoSynonyms(false);
260 configurator.setDoNamesWithoutTaxa(true);
261 configurator.setDoTaxaByCommonNames(true);
262
263 list = taxonService.findTaxaAndNamesForEditor(configurator);
264
265 Assert.assertEquals("Expecting one entity", 1, list.size());
266
267 }
268
269 @SuppressWarnings("rawtypes")
270 @Test
271 @DataSet
272 public final void testPurgeAndReindex() throws CorruptIndexException, IOException, ParseException {
273
274 refreshLuceneIndex();
275
276 Pager<SearchResult<TaxonBase>> pager;
277
278 pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 8
279 Assert.assertEquals("Expecting 8 entities", 8, pager.getCount().intValue());
280
281 indexer.purge(null);
282 commitAndStartNewTransaction(null);
283
284 pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 0
285 Assert.assertEquals("Expecting no entities since the index has been purged", 0, pager.getCount().intValue());
286
287 indexer.reindex(indexer.indexedClasses(), null);
288 commitAndStartNewTransaction(null);
289
290 pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 8
291 Assert.assertEquals("Expecting 8 entities", 8, pager.getCount().intValue());
292 }
293
294
295 @SuppressWarnings("rawtypes")
296 @Test
297 @DataSet
298 public final void testFindByDescriptionElementFullText_CommonName() throws CorruptIndexException, IOException,
299 ParseException {
300
301 refreshLuceneIndex();
302
303 Pager<SearchResult<TaxonBase>> pager;
304
305 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null, null,
306 false, null, null, null, null);
307 Assert.assertEquals("Expecting one entity when searching for CommonTaxonName", 1,
308 pager.getCount().intValue());
309
310 // the description containing the Nulltanne has no taxon attached,
311 // taxon.id = null
312 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Nulltanne", null, null, null,
313 false, null, null, null, null);
314 Assert.assertEquals("Expecting no entity when searching for 'Nulltanne' ", 0, pager.getCount().intValue());
315
316 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null,
317 Arrays.asList(new Language[] { Language.GERMAN() }), false, null, null, null, null);
318 Assert.assertEquals("Expecting one entity when searching in German", 1, pager.getCount().intValue());
319
320 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null,
321 Arrays.asList(new Language[] { Language.RUSSIAN() }), false, null, null, null, null);
322 Assert.assertEquals("Expecting no entity when searching in Russian", 0, pager.getCount().intValue());
323
324 }
325
326 @SuppressWarnings("rawtypes")
327 @Test
328 @DataSet
329 public final void testFindByDescriptionElementFullText_Distribution() throws CorruptIndexException, IOException, ParseException {
330
331 refreshLuceneIndex();
332
333 Pager<SearchResult<TaxonBase>> pager;
334 // by Area
335 pager = taxonService.findByDescriptionElementFullText(null, "Canada", null, null, null, false, null, null, null, null);
336 Assert.assertEquals("Expecting one entity when searching for arae 'Canada'", 1, pager.getCount().intValue());
337 // by Status
338 pager = taxonService.findByDescriptionElementFullText(null, "present", null, null, null, false, null, null, null, null);
339 Assert.assertEquals("Expecting one entity when searching for status 'present'", 1, pager.getCount().intValue());
340 }
341
342 @SuppressWarnings("rawtypes")
343 @Test
344 @DataSet
345 public final void testFindByDescriptionElementFullText_wildcard() throws CorruptIndexException, IOException, ParseException {
346
347 refreshLuceneIndex();
348
349 Pager<SearchResult<TaxonBase>> pager;
350
351 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"*", null, null, null, false, null, null, null, null);
352 Assert.assertEquals("Expecting one entity when searching for CommonTaxonName", 1, pager.getCount().intValue());
353 }
354
355 /**
356 * Regression test for #3113 (hibernate search: wildcard query can cause BooleanQuery$TooManyClauses: maxClauseCount is set to 1024)
357 *
358 * @throws CorruptIndexException
359 * @throws IOException
360 * @throws ParseException
361 */
362 @SuppressWarnings("rawtypes")
363 @Test
364 @DataSet
365 public final void testFindByDescriptionElementFullText_TooManyClauses() throws CorruptIndexException, IOException, ParseException {
366
367 // generate 1024 terms to reproduce the bug
368 TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
369 Set<String> uniqueRandomStrs = new HashSet<String>(1024);
370 while(uniqueRandomStrs.size() < 1024){
371 uniqueRandomStrs.add(RandomStringUtils.random(10, true, false));
372 }
373 for(String rndStr: uniqueRandomStrs){
374 description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
375 }
376 descriptionService.saveOrUpdate(description);
377 commitAndStartNewTransaction(null);
378
379 refreshLuceneIndex();
380
381 Pager<SearchResult<TaxonBase>> pager;
382
383 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, null, null, null, null);
384 Assert.assertEquals("Expecting all 1024 entities grouped into one SearchResult item when searching for Rot*", 1, pager.getCount().intValue());
385 }
386
387 /**
388 * Regression test for #3116 (fulltext search: always only one page of results)
389 *
390 * @throws CorruptIndexException
391 * @throws IOException
392 * @throws ParseException
393 */
394 @SuppressWarnings("rawtypes")
395 @Test
396 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
397 @Ignore
398 public final void testFullText_Paging() throws CorruptIndexException, IOException, ParseException {
399
400 Reference sec = ReferenceFactory.newDatabase();
401 referenceService.save(sec);
402
403 Set<String> uniqueRandomStrs = new HashSet<String>(1024);
404 int numOfItems = 100;
405 while(uniqueRandomStrs.size() < numOfItems){
406 uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
407 }
408
409 for(String rndStr: uniqueRandomStrs){
410
411 Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SERIES()), sec);
412 taxon.setTitleCache("Tax" + rndStr, true);
413 taxonService.save(taxon);
414
415 TaxonDescription description = TaxonDescription.NewInstance(taxon);
416 description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
417 descriptionService.saveOrUpdate(description);
418 }
419
420 commitAndStartNewTransaction(new String[]{"TAXONBASE"});
421 refreshLuceneIndex();
422
423 int pageSize = 10;
424
425 Pager<SearchResult<TaxonBase>> pager;
426
427 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, null, null, null);
428 Assert.assertEquals("unexpeted number of pages", Integer.valueOf(numOfItems / pageSize), pager.getPagesAvailable());
429 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 9, null, null);
430 Assert.assertNotNull("last page must have records", pager.getRecords());
431 Assert.assertNotNull("last item on last page must exist", pager.getRecords().get(0));
432 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 10, null, null);
433 Assert.assertNotNull("last page + 1 must not have any records", pager.getRecords());
434 }
435
436 /**
437 * test for max score and sort by score of hit groups
438 * with all matches per taxon in a single TextData element
439 * see {@link #testFullText_ScoreAndOrder_2()} for the complement
440 * test with matches in multiple TextData per taxon
441 *
442 * @throws CorruptIndexException
443 * @throws IOException
444 * @throws ParseException
445 */
446 @SuppressWarnings("rawtypes")
447 @Test
448 @DataSet
449 @Ignore // test fails, maybe the assumptions made here are not compatible with the lucene scoring mechanism see http://lucene.apache.org/core/3_6_1/scoring.html
450 public final void testFullText_ScoreAndOrder_1() throws CorruptIndexException, IOException, ParseException {
451
452 int numOfTaxa = 3;
453
454 UUID[] taxonUuids = new UUID[numOfTaxa];
455 StringBuilder text = new StringBuilder();
456
457 for(int i = 0; i < numOfTaxa; i++){
458
459 Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
460 taxon.setTitleCache("Taxon_" + i, true);
461 taxonUuids[i] = taxon.getUuid();
462 taxonService.save(taxon);
463
464 text.append(" ").append("Rot");
465 TaxonDescription description = TaxonDescription.NewInstance(taxon);
466 description.addElement(TextData.NewInstance(text.toString(), Language.DEFAULT(), null));
467 descriptionService.saveOrUpdate(description);
468 }
469
470 commitAndStartNewTransaction(null);
471 refreshLuceneIndex();
472
473 Pager<SearchResult<TaxonBase>> pager;
474
475 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
476 for(int i = 0; i < numOfTaxa; i++){
477 Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
478 }
479 Assert.assertEquals("max score should be equal to the score of the first element", pager.getRecords().get(0).getMaxScore(), pager.getRecords().get(0).getScore(), 0);
480 }
481
482 /**
483 * test for max score and sort by score of hit groups
484 * with all matches per taxon in a multiple TextData elements
485 * see {@link #testFullText_ScoreAndOrder_1()} for the complement
486 * test with matches in a single TextData per taxon
487 *
488 * @throws CorruptIndexException
489 * @throws IOException
490 * @throws ParseException
491 */
492 @SuppressWarnings("rawtypes")
493 @Test
494 @DataSet
495 @Ignore // test fails, maybe the assumptions made here are not compatible with the lucene scoring mechanism see http://lucene.apache.org/core/3_6_1/scoring.html
496 public final void testFullText_ScoreAndOrder_2() throws CorruptIndexException, IOException, ParseException {
497
498 int numOfTaxa = 3;
499
500 UUID[] taxonUuids = new UUID[numOfTaxa];
501
502 for(int i = 0; i < numOfTaxa; i++){
503
504 Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
505 taxon.setTitleCache("Taxon_" + i, true);
506 taxonUuids[i] = taxon.getUuid();
507 taxonService.save(taxon);
508
509 TaxonDescription description = TaxonDescription.NewInstance(taxon);
510 for(int k = 0; k < i; k++){
511 description.addElement(TextData.NewInstance("Rot", Language.DEFAULT(), null));
512 }
513 descriptionService.saveOrUpdate(description);
514 }
515
516 commitAndStartNewTransaction(null);
517 refreshLuceneIndex();
518
519 Pager<SearchResult<TaxonBase>> pager;
520
521 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
522 for(int i = 0; i < numOfTaxa; i++){
523 Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
524 }
525 Assert.assertEquals("max score should be equal to the score of the first element", pager.getRecords().get(0).getMaxScore(), pager.getRecords().get(0).getScore(), 0);
526 }
527
528
529 /**
530 * @throws CorruptIndexException
531 * @throws IOException
532 * @throws ParseException
533 * @throws LuceneMultiSearchException
534 */
535 @Test
536 @DataSet
537 public final void testFullText_Grouping() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
538
539 TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
540 Set<String> uniqueRandomStrs = new HashSet<String>(1024);
541 int numOfItems = 100;
542 while(uniqueRandomStrs.size() < numOfItems){
543 uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
544 }
545 for(String rndStr: uniqueRandomStrs){
546 description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
547 }
548 descriptionService.saveOrUpdate(description);
549
550 commitAndStartNewTransaction(new String[]{"DESCRIPTIONELEMENTBASE"});
551
552 refreshLuceneIndex();
553
554 int pageSize = 10;
555
556 Pager<SearchResult<TaxonBase>> pager;
557 boolean highlightFragments = true;
558
559 // test with findByDescriptionElementFullText
560 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, highlightFragments, pageSize, null, null, null);
561 logSearchResults(pager, Level.DEBUG, null);
562 Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
563 Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
564 Map<String, String[]> highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
565 // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
566 int maxDocsPerGroup = 10;
567 Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
568
569 // test with findByEverythingFullText
570 pager = taxonService.findByEverythingFullText( "Rot*", null, null, highlightFragments, pageSize, null, null, null);
571 logSearchResults(pager, Level.DEBUG, null);
572 Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
573 Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
574 highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
575 // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
576 maxDocsPerGroup = 10;
577 Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
578
579 }
580
581 @SuppressWarnings("rawtypes")
582 @Test
583 @DataSet
584 @Ignore
585 public final void testFindByDescriptionElementFullText_TextData() throws CorruptIndexException, IOException, ParseException {
586
587 refreshLuceneIndex();
588
589 Pager<SearchResult<TaxonBase>> pager;
590 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, false, null, null, null, null);
591 logSearchResults(pager, Level.DEBUG, null);
592 Assert.assertEquals("Expecting one entity when searching for any TextData", 1, pager.getCount().intValue());
593 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
594 Assert.assertTrue("Expecting two docs, one for RUSSIAN and one for GERMAN", pager.getRecords().get(0).getDocs().size() == 2);
595 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
596
597
598 pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, null, null, false, null, null, null, null);
599 Assert.assertEquals("Expecting one entity when searching for any type", 1, pager.getCount().intValue());
600
601 pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.UNKNOWN()}), null, false, null, null, null, null);
602 Assert.assertEquals("Expecting one entity when searching for any type and for Feature DESCRIPTION", 1, pager.getCount().intValue());
603
604 pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.CHROMOSOME_NUMBER()}), null, false, null, null, null, null);
605 Assert.assertEquals("Expecting no entity when searching for any type and for Feature CHROMOSOME_NUMBER", 0, pager.getCount().intValue());
606
607 pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.CHROMOSOME_NUMBER(), Feature.UNKNOWN()}), null, false, null, null, null, null);
608 Assert.assertEquals("Expecting no entity when searching for any type and for Feature DESCRIPTION or CHROMOSOME_NUMBER", 1, pager.getCount().intValue());
609
610 pager = taxonService.findByDescriptionElementFullText(Distribution.class, "Abies", null, null, null, false, null, null, null, null);
611 Assert.assertEquals("Expecting no entity when searching for Distribution", 0, pager.getCount().intValue());
612
613 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{}), false, null, null, null, null);
614 Assert.assertEquals("Expecting one entity", 1, pager.getCount().intValue());
615 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
616
617 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{Language.RUSSIAN()}), false, null, null, null, null);
618 Assert.assertEquals("Expecting one entity", 1, pager.getCount().intValue());
619 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
620
621 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
622 Assert.assertEquals("Expecting no entity", 0, pager.getCount().intValue());
623
624 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
625 Assert.assertEquals("Expecting one entity", 1, pager.getCount().intValue());
626 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
627 }
628
629 @SuppressWarnings("rawtypes")
630 @Test
631 @DataSet
632 public final void testFindByDescriptionElementFullText_MultipleWords() throws CorruptIndexException, IOException, ParseException {
633
634 refreshLuceneIndex();
635
636 // Pflanzenart aus der Gattung der Tannen
637 long start = System.currentTimeMillis();
638
639 Pager<SearchResult<TaxonBase>> pager;
640 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Tannen", null, null, null, false, null, null, null, null);
641 Assert.assertEquals("OR search : Expecting one entity", 1, pager.getCount().intValue());
642
643 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Wespen", null, null, null, false, null, null, null, null);
644 Assert.assertEquals("OR search : Expecting one entity", 1, pager.getCount().intValue());
645
646 pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Tannen", null, null, null, false, null, null, null, null);
647 Assert.assertEquals("AND search : Expecting one entity", 1, pager.getCount().intValue());
648
649 pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Wespen", null, null, null, false, null, null, null, null);
650 Assert.assertEquals("AND search : Expecting no entity", 0, pager.getCount().intValue());
651
652 pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Tannen\"", null, null, null, false, null, null, null, null);
653 Assert.assertEquals("Phrase search : Expecting one entity", 1, pager.getCount().intValue());
654
655 pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Wespen\"", null, null, null, false, null, null, null, null);
656 Assert.assertEquals("Phrase search : Expecting one entity", 0, pager.getCount().intValue());
657
658 logger.info("testFindByDescriptionElementFullText_MultipleWords() duration: " + (System.currentTimeMillis() - start) + "ms");
659
660 }
661
662
663 @SuppressWarnings("rawtypes")
664 @Test
665 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
666 public final void testFindByDescriptionElementFullText_modify_DescriptionElement() throws CorruptIndexException, IOException, ParseException {
667
668 refreshLuceneIndex();
669
670 Pager<SearchResult<TaxonBase>> pager;
671 //
672 // modify the DescriptionElement
673 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
674 Assert.assertTrue("Search did not return any results", pager.getRecords().size() > 0);
675 Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
676 Document indexDocument = pager.getRecords().get(0).getDocs().iterator().next();
677 String[] descriptionElementUuidStr = indexDocument.getValues("uuid");
678 String[] inDescriptionUuidStr = indexDocument.getValues("inDescription.uuid");
679 // is only one uuid!
680 DescriptionElementBase textData = descriptionService.getDescriptionElementByUuid(UUID.fromString(descriptionElementUuidStr[0]));
681
682 ((TextData)textData).removeText(Language.GERMAN());
683 ((TextData)textData).putText(Language.SPANISH_CASTILIAN(), "abeto bals"+UTF8.SMALL_A_ACUTE+"mico");
684
685 descriptionService.saveDescriptionElement(textData);
686 commitAndStartNewTransaction(null);
687 // printDataSet(System.out, new String[] {
688 // "DESCRIPTIONELEMENTBASE", "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING" }
689 // );
690
691 //
692 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
693 Assert.assertEquals("The german 'Balsam-Tanne' TextData should no longer be indexed", 0, pager.getCount().intValue());
694 pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
695 Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico'", 1, pager.getCount().intValue());
696 pager = taxonService.findByDescriptionElementFullText(TextData.class, "bals"+UTF8.SMALL_A_ACUTE+"mico", null, null, null, false, null, null, null, null);
697 Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico'", 1, pager.getCount().intValue());
698
699 //
700 // modify the DescriptionElement via the Description object
701 DescriptionBase<?> description = descriptionService.find(UUID.fromString(inDescriptionUuidStr[0]));
702 Set<DescriptionElementBase> elements = description.getElements();
703 for( DescriptionElementBase elm : elements){
704 if(elm.getUuid().toString().equals(descriptionElementUuidStr[0])){
705 ((TextData)elm).removeText(Language.SPANISH_CASTILIAN());
706 ((TextData)elm).putText(Language.POLISH(), "Jod"+UTF8.POLISH_L+"a balsamiczna");
707 }
708 }
709 descriptionService.saveOrUpdate(description);
710 commitAndStartNewTransaction(null);
711 pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
712 Assert.assertEquals("The spanish 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico' TextData should no longer be indexed", 0, pager.getCount().intValue());
713 pager = taxonService.findByDescriptionElementFullText(TextData.class, "balsamiczna", null, null, Arrays.asList(new Language[]{Language.POLISH()}), false, null, null, null, null);
714 Assert.assertEquals("expecting to find the POLISH 'Jod"+UTF8.POLISH_L+"a balsamiczna'", 1, pager.getCount().intValue());
715 }
716
717 @SuppressWarnings("rawtypes")
718 @Test
719 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
720 public final void testFindByDescriptionElementFullText_modify_Taxon() throws CorruptIndexException, IOException, ParseException {
721
722 refreshLuceneIndex();
723
724 Pager<SearchResult<TaxonBase>> pager;
725 Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
726 TaxonDescription d_abies_balsamea = (TaxonDescription)descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
727
728 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
729 Assert.assertEquals("expecting to find the GERMAN 'Balsam-Tanne'", 1, pager.getCount().intValue());
730
731 // exchange the Taxon with another one via the Taxon object
732 // 1.) remove existing description:
733 t_abies_balsamea.removeDescription(d_abies_balsamea);
734
735 taxonService.saveOrUpdate(t_abies_balsamea);
736 commitAndStartNewTransaction(null);
737
738 t_abies_balsamea = (Taxon)taxonService.find(t_abies_balsamea.getUuid());
739
740 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
741 Assert.assertEquals("'Balsam-Tanne' should no longer be found", 0, pager.getCount().intValue());
742
743 // 2.) create new description and add to taxon:
744 TaxonDescription d_abies_balsamea_new = TaxonDescription.NewInstance();
745 d_abies_balsamea_new
746 .addElement(TextData
747 .NewInstance(
748 "Die Balsamtanne ist mit bis zu 30 m Höhe ein mittelgro"+UTF8.SHARP_S+"er Baum und kann bis zu 200 Jahre alt werden",
749 Language.GERMAN(), null));
750 t_abies_balsamea.addDescription(d_abies_balsamea_new);
751 // set authorshipCache to null to avoid validation exception,
752 // this is maybe not needed in future, see ticket #3344
753 BotanicalName abies_balsamea = HibernateProxyHelper.deproxy(t_abies_balsamea.getName(), BotanicalName.class);
754 abies_balsamea.setAuthorshipCache(null);
755 printDataSet(System.err, new String[] {"LANGUAGESTRING_AUD"});
756 taxonService.saveOrUpdate(t_abies_balsamea);
757 commitAndStartNewTransaction(null);
758
759 // printDataSet(System.out, new String[] {
760 // "DESCRIPTIONBASE"
761 // });
762
763 pager = taxonService.findByDescriptionElementFullText(TextData.class, "mittelgro"+UTF8.SHARP_S+"er Baum", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
764 Assert.assertEquals("the taxon should be found via the new Description", 1, pager.getCount().intValue());
765 }
766
767 @SuppressWarnings("rawtypes")
768 @Test
769 @DataSet
770 public final void testFindByDescriptionElementFullText_modify_Classification() throws CorruptIndexException, IOException, ParseException {
771
772 refreshLuceneIndex();
773
774 Pager<SearchResult<TaxonBase>> pager;
775
776 // put taxon into other classification, new taxon node
777 Classification classification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
778 Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
779
780 // TODO: why is the test failing when the childNode is already retrieved here, and not after the following four lines?
781 //TaxonNode childNode = classification.getChildNodes().iterator().next();
782
783 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
784 Assert.assertEquals("expecting to find the GERMAN 'Balsam-Tanne' even if filtering by classification", 1, pager.getCount().intValue());
785 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", alternateClassification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
786 Assert.assertEquals("GERMAN 'Balsam-Tanne' should NOT be found in other classification", 0, pager.getCount().intValue());
787
788 // check for the right taxon node
789 TaxonNode childNode = classification.getChildNodes().iterator().next();
790 Assert.assertEquals("expecting Abies balsamea sec.", childNode.getTaxon().getUuid().toString(), ABIES_BALSAMEA_UUID);
791 Assert.assertEquals("expecting default classification", childNode.getClassification().getUuid().toString(), CLASSIFICATION_UUID);
792
793 // moving the taxon around, the rootnode is only a proxy
794 alternateClassification.setRootNode(HibernateProxyHelper.deproxy(alternateClassification.getRootNode(), TaxonNode.class));
795 alternateClassification.addChildNode(childNode, null, null);
796
797 classificationService.saveOrUpdate(alternateClassification);
798 commitAndStartNewTransaction(null);
799
800 // printDataSet(System.out, new String[] {
801 // "TAXONBASE", "TAXONNODE", "CLASSIFICATION"
802 // });
803
804 // reload classification
805 classification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
806 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", alternateClassification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
807 Assert.assertEquals("GERMAN 'Balsam-Tanne' should now be found in other classification", 1, pager.getCount().intValue());
808
809 classification.getChildNodes().clear();
810 classificationService.saveOrUpdate(classification);
811 commitAndStartNewTransaction(null);
812
813 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", classification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
814 Assert.assertEquals("Now the GERMAN 'Balsam-Tanne' should NOT be found in original classification", 0, pager.getCount().intValue());
815
816 }
817
818 @SuppressWarnings("rawtypes")
819 @Test
820 @DataSet
821 public final void testFindByDescriptionElementFullText_CategoricalData() throws CorruptIndexException, IOException, ParseException {
822
823 // add CategoricalData
824 DescriptionBase d_abies_balsamea = descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
825 // Categorical data
826 CategoricalData cdata = CategoricalData.NewInstance();
827 cdata.setFeature(Feature.DESCRIPTION());
828 State state = State.NewInstance("green", "green", "gn");
829
830 StateData statedata = StateData.NewInstance(state);
831 statedata.putModifyingText(Language.ENGLISH(), "always, even during winter");
832 cdata.addStateData(statedata);
833 d_abies_balsamea.addElement(cdata);
834
835 UUID termUUID = termService.save(state).getUuid();
836 descriptionService.save(d_abies_balsamea);
837
838 commitAndStartNewTransaction(null);
839
840 // printDataSet(System.out, new String[] {
841 // "STATEDATA", "STATEDATA_DEFINEDTERMBASE", "STATEDATA_LANGUAGESTRING", "LANGUAGESTRING"});
842
843 refreshLuceneIndex();
844
845 Pager<SearchResult<TaxonBase>> pager;
846 pager = taxonService.findByDescriptionElementFullText(CategoricalData.class, "green", null, null, null, false, null, null, null, null);
847 Assert.assertEquals("Expecting one entity", 1, pager.getCount().intValue());
848 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
849 Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
850 Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
851
852
853 //TODO modify the StateData
854 TaxonBase taxon = pager.getRecords().get(0).getEntity();
855
856 String newName = "Quercus robur";
857 taxon.setTitleCache(newName + " sec. ", true);
858
859 taxonService.saveOrUpdate(taxon);
860 commitAndStartNewTransaction(null);
861
862 taxon = taxonService.find(taxon.getUuid());
863 Assert.assertEquals(newName + " sec. ", taxon.getTitleCache());
864 DefinedTermBase term = termService.find(termUUID);
865
866 termService.delete(term);
867
868 }
869
870 @SuppressWarnings("rawtypes")
871 @Test
872 @DataSet
873 public final void testFindByDescriptionElementFullText_Highlighting() throws CorruptIndexException, IOException, ParseException {
874
875 refreshLuceneIndex();
876
877 Pager<SearchResult<TaxonBase>> pager;
878 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, true, null, null, null, null);
879 Assert.assertEquals("Expecting one entity when searching for any TextData", 1, pager.getCount().intValue());
880 SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
881 Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
882 String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
883 Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Abies</B>"));
884
885 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Tannen", null, null, null, true, null, null, null, null);
886 searchResult = pager.getRecords().get(0);
887 Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
888 fragments = searchResult.getFieldHighlightMap().values().iterator().next();
889 Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Pflanzenart</B>") || fragments[0].contains("<B>Tannen</B>"));
890
891 pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Tannen", null, null, null, true, null, null, null, null);
892 searchResult = pager.getRecords().get(0);
893 Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
894 fragments = searchResult.getFieldHighlightMap().values().iterator().next();
895 Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Pflanzenart</B>") && fragments[0].contains("<B>Tannen</B>"));
896
897 pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Tannen\"", null, null, null, true, null, null, null, null);
898 searchResult = pager.getRecords().get(0);
899 Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
900 fragments = searchResult.getFieldHighlightMap().values().iterator().next();
901 Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Pflanzenart</B> <B>aus</B> <B>der</B> <B>Gattung</B> <B>der</B> <B>Tannen</B>"));
902
903 pager = taxonService.findByDescriptionElementFullText(TextData.class, "Gatt*", null, null, null, true, null, null, null, null);
904 searchResult = pager.getRecords().get(0);
905 Assert.assertTrue("Wildcard search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
906 fragments = searchResult.getFieldHighlightMap().values().iterator().next();
907 Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Gatt"));
908 }
909
910
911 @Test
912 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
913 public final void testFindByFullText() throws CorruptIndexException, IOException, ParseException {
914
915 refreshLuceneIndex();
916
917 Classification europeanAbiesClassification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
918
919 Pager<SearchResult<TaxonBase>> pager;
920
921 pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 7
922 logSearchResults(pager, Level.DEBUG, null);
923 Assert.assertEquals("Expecting 8 entities", 8, pager.getCount().intValue());
924
925 pager = taxonService.findByFullText(Taxon.class, "Abies", null, null, true, null, null, null, null); // --> 6
926 Assert.assertEquals("Expecting 7 entities", 7, pager.getCount().intValue());
927
928 pager = taxonService.findByFullText(Synonym.class, "Abies", null, null, true, null, null, null, null); // --> 1
929 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
930
931 pager = taxonService.findByFullText(TaxonBase.class, "sec", null, null, true, null, null, null, null); // --> 7
932 Assert.assertEquals("Expecting 8 entities", 9, pager.getCount().intValue());
933
934 pager = taxonService.findByFullText(null, "genus", null, null, true, null, null, null, null); // --> 1
935 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
936
937 pager = taxonService.findByFullText(Taxon.class, "subalpina", null, null, true, null, null, null, null); // --> 0
938 Assert.assertEquals("Expecting 0 entities", 0, pager.getCount().intValue());
939
940 // synonym in classification ???
941 }
942
943 @Test
944 @DataSet
945 public final void testPrepareByAreaSearch() throws IOException, ParseException {
946
947 List<PresenceAbsenceTerm> statusFilter = new ArrayList<PresenceAbsenceTerm>();
948 List<NamedArea> areaFilter = new ArrayList<NamedArea>();
949 areaFilter.add(germany);
950 areaFilter.add(canada);
951 areaFilter.add(russia);
952
953 Pager<SearchResult<TaxonBase>> pager = taxonService.findByDistribution(areaFilter, statusFilter, null, 20, 0, null, null);
954 Assert.assertEquals("Expecting 2 entities", Integer.valueOf(2), Integer.valueOf(pager.getRecords().size()));
955
956 }
957
958 @Test
959 @DataSet
960 public final void testFindTaxaAndNamesByFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
961
962 refreshLuceneIndex();
963
964 Pager<SearchResult<TaxonBase>> pager;
965
966 Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
967
968
969 pager = taxonService.findTaxaAndNamesByFullText(
970 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
971 "Abies", null, null, null, null, true, null, null, null, null);
972 // logPagerRecords(pager, Level.DEBUG);
973 Assert.assertEquals("doTaxa & doSynonyms", 8, pager.getCount().intValue());
974
975 pager = taxonService.findTaxaAndNamesByFullText(
976 EnumSet.allOf(TaxaAndNamesSearchMode.class),
977 "Abies", null, null, null, null, true, null, null, null, null);
978 // logPagerRecords(pager, Level.DEBUG);
979 Assert.assertEquals("all search modes", 8, pager.getCount().intValue());
980
981 pager = taxonService.findTaxaAndNamesByFullText(
982 EnumSet.allOf(TaxaAndNamesSearchMode.class),
983 "Abies", alternateClassification, null, null, null, true, null, null, null, null);
984 // logPagerRecords(pager, Level.DEBUG);
985 Assert.assertEquals("all search modes, filtered by alternateClassification", 1, pager.getCount().intValue());
986
987 pager = taxonService.findTaxaAndNamesByFullText(
988 EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
989 "Abies", null, null, null, null, true, null, null, null, null);
990 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
991 SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
992 Assert.assertEquals(Synonym.class, searchResult.getEntity().getClass());
993 // Abies subalpina sec. Kohlbecker, A., Testcase standart views, 2013
994
995
996 pager = taxonService.findTaxaAndNamesByFullText(
997 EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
998 "Abies", null, null, null, null, true, null, null, null, null);
999 Assert.assertEquals("Expecting 0 entity", 0, pager.getCount().intValue());
1000
1001
1002 pager = taxonService.findTaxaAndNamesByFullText(
1003 EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
1004 "Tanne", null, null, null, null, true, null, null, null, null);
1005 Assert.assertEquals("Expecting 1 entity", 1, pager.getRecords().size());
1006 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
1007
1008 pager = taxonService.findTaxaAndNamesByFullText(
1009 EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1010 "kawakamii", null, null, null, null, true, null, null, null, null);
1011 logSearchResults(pager, Level.DEBUG, null);
1012 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
1013
1014 }
1015
1016 @Test
1017 @DataSet
1018 public final void testFindTaxaAndNamesByFullText_Sort() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1019
1020 refreshLuceneIndex();
1021
1022 Pager<SearchResult<TaxonBase>> pager;
1023
1024 List<OrderHint> orderHints = new ArrayList<OrderHint>();
1025
1026 String[] docFields2log = new String[]{"id"};
1027
1028 // SortById
1029 orderHints.addAll(OrderHint.ORDER_BY_ID.asList());
1030 pager = taxonService.findTaxaAndNamesByFullText(
1031 EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
1032 "Abies", null, null, null, null, true, null, null, orderHints, null);
1033 // logSearchResults(pager, Level.DEBUG, docFields2log);
1034 int lastId = -1;
1035 for(SearchResult<TaxonBase> rs : pager.getRecords()){
1036 if(lastId != -1){
1037 Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
1038 }
1039 lastId = rs.getEntity().getId();
1040 }
1041
1042 orderHints.addAll(OrderHint.ORDER_BY_ID.asList());
1043 pager = taxonService.findTaxaAndNamesByFullText(
1044 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1045 "Abies", null, null, null, null, true, null, null, orderHints, null);
1046 // logSearchResults(pager, Level.DEBUG, docFields2log);
1047
1048 lastId = -1;
1049 for(SearchResult<TaxonBase> rs : pager.getRecords()){
1050 if(lastId != -1){
1051 Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
1052 }
1053 lastId = rs.getEntity().getId();
1054 }
1055
1056 // Sortby NOMENCLATURAL_SORT_ORDER TODO make assertions !!!
1057 orderHints.clear();
1058 orderHints.addAll(OrderHint.NOMENCLATURAL_SORT_ORDER.asList());
1059 pager = taxonService.findTaxaAndNamesByFullText(
1060 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1061 "Abies", null, null, null, null, true, null, null, orderHints, null);
1062 logSearchResults(pager, Level.DEBUG, null);
1063
1064 }
1065
1066 @Test
1067 @DataSet
1068 public final void testFindTaxaAndNamesByFullText_AreaFilter() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1069
1070 refreshLuceneIndex();
1071
1072 Pager<SearchResult<TaxonBase>> pager;
1073
1074 Set<NamedArea> a_germany_canada_russia = new HashSet<NamedArea>();
1075 a_germany_canada_russia.add(germany);
1076 a_germany_canada_russia.add(canada);
1077 a_germany_canada_russia.add(russia);
1078
1079 Set<NamedArea> a_russia = new HashSet<NamedArea>();
1080 a_russia.add(russia);
1081
1082 Set<PresenceAbsenceTerm> present = new HashSet<PresenceAbsenceTerm>();
1083 present.add(PresenceAbsenceTerm.PRESENT());
1084
1085 Set<PresenceAbsenceTerm> present_native = new HashSet<PresenceAbsenceTerm>();
1086 present_native.add(PresenceAbsenceTerm.PRESENT());
1087 present_native.add(PresenceAbsenceTerm.NATIVE());
1088
1089 Set<PresenceAbsenceTerm> absent = new HashSet<PresenceAbsenceTerm>();
1090 absent.add(PresenceAbsenceTerm.ABSENT());
1091
1092 pager = taxonService.findTaxaAndNamesByFullText(
1093 EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
1094 "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1095 logSearchResults(pager, Level.DEBUG, null);
1096
1097 // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1098 pager = taxonService.findTaxaAndNamesByFullText(
1099 EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
1100 "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1101 Assert.assertEquals("synonyms with matching area filter", 1, pager.getCount().intValue());
1102
1103 pager = taxonService.findTaxaAndNamesByFullText(
1104 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1105 "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1106 logSearchResults(pager, Level.DEBUG, null);
1107 Assert.assertEquals("taxa and synonyms with matching area filter", 3, pager.getCount().intValue());
1108
1109 pager = taxonService.findTaxaAndNamesByFullText(
1110 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1111 "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1112 Assert.assertEquals("taxa and synonyms with matching area & status filter 1", 3, pager.getCount().intValue());
1113
1114 pager = taxonService.findTaxaAndNamesByFullText(
1115 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1116 "Abies", null, a_germany_canada_russia, present, null, true, null, null, null, null);
1117 Assert.assertEquals("taxa and synonyms with matching area & status filter 2", 2, pager.getCount().intValue());
1118
1119 pager = taxonService.findTaxaAndNamesByFullText(
1120 EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1121 "Abies", null, a_russia, present, null, true, null, null, null, null);
1122 Assert.assertEquals("taxa and synonyms with non matching area & status filter", 0, pager.getCount().intValue());
1123
1124 pager = taxonService.findTaxaAndNamesByFullText(
1125 EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
1126 "Tanne", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1127 Assert.assertEquals("ByCommonNames with area filter", 1, pager.getCount().intValue());
1128
1129 // abies_kawakamii_sensu_komarov as misapplied name for t_abies_balsamea
1130 pager = taxonService.findTaxaAndNamesByFullText(
1131 EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1132 "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1133 Assert.assertEquals("misappliedNames with matching area & status filter", 1, pager.getCount().intValue());
1134
1135
1136 // 1. remove existing taxon relation
1137 Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
1138 Set<TaxonRelationship> relsTo = t_abies_balsamea.getRelationsToThisTaxon();
1139 Assert.assertEquals(1, relsTo.size());
1140 TaxonRelationship taxonRelation = relsTo.iterator().next();
1141 t_abies_balsamea.removeTaxonRelation(taxonRelation);
1142 taxonService.saveOrUpdate(t_abies_balsamea);
1143 commitAndStartNewTransaction(null);
1144
1145 pager = taxonService.findTaxaAndNamesByFullText(
1146 EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1147 "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1148 Assert.assertEquals("misappliedNames with matching area & status filter, should match nothing now", 0, pager.getCount().intValue());
1149
1150 // 2. now add abies_kawakamii_sensu_komarov as misapplied name for t_abies_alba and search for misapplications in russia: ABSENT
1151 Taxon t_abies_kawakamii_sensu_komarov = (Taxon)taxonService.find(UUID.fromString(D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID));
1152 Taxon t_abies_alba = (Taxon)taxonService.find(UUID.fromString(ABIES_ALBA_UUID));
1153 t_abies_alba.addMisappliedName(t_abies_kawakamii_sensu_komarov, null, null);
1154
1155 taxonService.update(t_abies_kawakamii_sensu_komarov);
1156
1157 commitAndStartNewTransaction(null);
1158
1159 pager = taxonService.findTaxaAndNamesByFullText(
1160 EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1161 "Abies", null, a_germany_canada_russia, absent, null, true, null, null, null, null);
1162 Assert.assertEquals("misappliedNames with matching area & status filter, should find one", 1, pager.getCount().intValue());
1163
1164 }
1165
1166 @Test
1167 @DataSet
1168 @Ignore // remove once http://dev.e-taxonomy.eu/trac/ticket/5477 is solved
1169 public final void testFindTaxaAndNamesByFullText_AreaFilter_issue5477() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1170
1171 Set<NamedArea> a_germany_canada_russia = new HashSet<NamedArea>();
1172 a_germany_canada_russia.add(germany);
1173 a_germany_canada_russia.add(canada);
1174 a_germany_canada_russia.add(russia);
1175
1176
1177 Set<PresenceAbsenceTerm> absent = new HashSet<PresenceAbsenceTerm>();
1178 absent.add(PresenceAbsenceTerm.ABSENT());
1179
1180 Taxon t_abies_kawakamii_sensu_komarov = (Taxon)taxonService.find(UUID.fromString(D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID));
1181 Taxon t_abies_alba = (Taxon)taxonService.find(UUID.fromString(ABIES_ALBA_UUID));
1182 t_abies_alba.addMisappliedName(t_abies_kawakamii_sensu_komarov, null, null);
1183
1184 /* Since the upgrade from hibernate search 4 to 5.5
1185 * triggering an update of t_abies_alba is no longer sufficient to also update the
1186 * document of t_abies_kawakamii_sensu_komarov in the lucene index.
1187 * the last test in testFindTaxaAndNamesByFullText_AreaFilter() failed in this case.
1188 * This situation is reproduced here:
1189 */
1190 taxonService.update(t_abies_alba);
1191
1192 commitAndStartNewTransaction(null);
1193
1194 Pager pager = taxonService.findTaxaAndNamesByFullText(
1195 EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1196 "Abies", null, a_germany_canada_russia, absent, null, true, null, null, null, null);
1197 Assert.assertEquals("misappliedNames with matching area & status filter, should find one", 1, pager.getCount().intValue());
1198 }
1199
1200
1201 /**
1202 * Regression test for #3119: fulltext search: Entity always null whatever search
1203 *
1204 * @throws CorruptIndexException
1205 * @throws IOException
1206 * @throws ParseException
1207 * @throws LuceneMultiSearchException
1208 */
1209 @Test
1210 @DataSet
1211 public final void testFindByEverythingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1212
1213 refreshLuceneIndex();
1214
1215 Pager<SearchResult<TaxonBase>> pager;
1216
1217 // via Taxon
1218 pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1219 logSearchResults(pager, Level.DEBUG, null);
1220 Assert.assertTrue("Expecting at least 7 entities for 'Abies'", pager.getCount() > 7);
1221 Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1222 Assert.assertEquals("Expecting Taxon entity", Taxon.class, pager.getRecords().get(0).getEntity().getClass());
1223
1224 // via DescriptionElement
1225 pager = taxonService.findByEverythingFullText("present", null, null, true, null, null, null, null);
1226 Assert.assertEquals("Expecting one entity when searching for area 'present'", 1, pager.getCount().intValue());
1227 Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1228 Assert.assertEquals("Expecting Taxon entity", Taxon.class, CdmBase.deproxy(pager.getRecords().get(0).getEntity()).getClass());
1229 Assert.assertEquals("Expecting Taxon ", ABIES_BALSAMEA_UUID, pager.getRecords().get(0).getEntity().getUuid().toString());
1230
1231 }
1232
1233
1234 @Test
1235 @DataSet
1236 public final void findByEveryThingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1237
1238 refreshLuceneIndex();
1239
1240 Pager<SearchResult<TaxonBase>> pager;
1241
1242 pager = taxonService.findByEverythingFullText("genus", null, null, false, null, null, null, null); // --> 1
1243 Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
1244
1245 //FIXME FAILS: abies balamea is returned twice, see also testFullText_Grouping()
1246 pager = taxonService.findByEverythingFullText("Balsam", null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
1247 logSearchResults(pager, Level.DEBUG, null);
1248 Assert.assertEquals("expecting to find the Abies balsamea via the GERMAN DescriptionElements", 1, pager.getCount().intValue());
1249
1250 pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1251 Assert.assertEquals("Expecting 8 entities", 8, pager.getCount().intValue());
1252 SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
1253 Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
1254 String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
1255 Assert.assertTrue("first fragments should contains serch term", fragments[0].toLowerCase().contains("<b>abies</b>"));
1256 }
1257
1258 // @SuppressWarnings("rawtypes")
1259 // @Test
1260 // @DataSet
1261 // public final void benchmarkFindTaxaAndNamesHql() throws CorruptIndexException, IOException, ParseException {
1262 //
1263 // createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1264 //
1265 // IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl();
1266 // configurator.setTitleSearchString("Wei"+UTF8.SHARP_S+"%");
1267 // configurator.setMatchMode(MatchMode.BEGINNING);
1268 // configurator.setDoTaxa(false);
1269 // configurator.setDoSynonyms(false);
1270 // configurator.setDoNamesWithoutTaxa(false);
1271 // configurator.setDoTaxaByCommonNames(true);
1272 //
1273 // Pager<IdentifiableEntity> pager;
1274 //
1275 // long startMillis = System.currentTimeMillis();
1276 // for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1277 // pager = taxonService.findTaxaAndNames(configurator);
1278 // if (logger.isDebugEnabled()) {
1279 // logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1280 // }
1281 // }
1282 // double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1283 // logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1284 // }
1285
1286 @SuppressWarnings("rawtypes")
1287 @Test
1288 @DataSet
1289 public final void benchmarkFindByCommonNameHql() throws CorruptIndexException, IOException, ParseException {
1290
1291 // printDataSet(System.err, new String[] { "TaxonBase" });
1292
1293 createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1294
1295 IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl<>();
1296 configurator.setTitleSearchString("Wei"+UTF8.SHARP_S+"%");
1297 configurator.setMatchMode(MatchMode.BEGINNING);
1298 configurator.setDoTaxa(false);
1299 configurator.setDoSynonyms(false);
1300 configurator.setDoNamesWithoutTaxa(false);
1301 configurator.setDoTaxaByCommonNames(true);
1302
1303 Pager<IdentifiableEntity> pager;
1304
1305 long startMillis = System.currentTimeMillis();
1306 for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1307 pager = taxonService.findTaxaAndNames(configurator);
1308 if (logger.isDebugEnabled()) {
1309 logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1310 }
1311 }
1312 double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1313 logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1314 }
1315
1316 @SuppressWarnings("rawtypes")
1317 @Test
1318 @DataSet
1319 public final void benchmarkFindByCommonNameLucene() throws CorruptIndexException, IOException, ParseException {
1320
1321 createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1322
1323 refreshLuceneIndex();
1324
1325 Pager<SearchResult<TaxonBase>> pager;
1326
1327 long startMillis = System.currentTimeMillis();
1328 for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1329 pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"*", null, null, null, false, null, null, null, null);
1330 if (logger.isDebugEnabled()) {
1331 logger.debug("[" + indx + "]" + pager.getRecords().get(0).getEntity().getTitleCache());
1332 }
1333 }
1334 double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1335 logger.info("Benchmark result - [find taxon by CommonName via lucene] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1336 }
1337
1338 /**
1339 * uncomment @Test annotation to create the dataset for this test
1340 */
1341 @Override
1342 // @Test
1343 @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="BlankDataSet.xml")
1344 public final void createTestDataSet() throws FileNotFoundException {
1345
1346 Classification europeanAbiesClassification = Classification.NewInstance("European Abies");
1347 europeanAbiesClassification.setUuid(UUID.fromString(CLASSIFICATION_UUID));
1348 classificationService.save(europeanAbiesClassification);
1349
1350 Classification alternativeClassification = Classification.NewInstance("Abies alternative");
1351 alternativeClassification.setUuid(UUID.fromString(CLASSIFICATION_ALT_UUID));
1352 classificationService.save(alternativeClassification);
1353
1354 Reference sec = ReferenceFactory.newBook();
1355 sec.setTitleCache("Kohlbecker, A., Testcase standart views, 2013", true);
1356 Reference sec_sensu = ReferenceFactory.newBook();
1357 sec_sensu.setTitleCache("Komarov, V. L., Flora SSSR 29", true);
1358 referenceService.save(sec);
1359 referenceService.save(sec_sensu);
1360
1361 BotanicalName n_abies = BotanicalName.NewInstance(Rank.GENUS());
1362 n_abies.setNameCache("Abies", true);
1363 Taxon t_abies = Taxon.NewInstance(n_abies, sec);
1364 taxonService.save(t_abies);
1365
1366 BotanicalName n_abies_alba = BotanicalName.NewInstance(Rank.SPECIES());
1367 n_abies_alba.setNameCache("Abies alba", true);
1368 Taxon t_abies_alba = Taxon.NewInstance(n_abies_alba, sec);
1369 t_abies_alba.setUuid(UUID.fromString(ABIES_ALBA_UUID));
1370 taxonService.save(t_abies_alba);
1371
1372 BotanicalName n_abies_subalpina = BotanicalName.NewInstance(Rank.SPECIES());
1373 n_abies_subalpina.setNameCache("Abies subalpina", true);
1374 Synonym s_abies_subalpina = Synonym.NewInstance(n_abies_subalpina, sec);
1375 taxonService.save(s_abies_subalpina);
1376
1377 BotanicalName n_abies_balsamea = BotanicalName.NewInstance(Rank.SPECIES());
1378 n_abies_balsamea.setNameCache("Abies balsamea", true);
1379 Taxon t_abies_balsamea = Taxon.NewInstance(n_abies_balsamea, sec);
1380 t_abies_balsamea.setUuid(UUID.fromString(ABIES_BALSAMEA_UUID));
1381 t_abies_balsamea.addSynonym(s_abies_subalpina, SynonymType.SYNONYM_OF());
1382 taxonService.save(t_abies_balsamea);
1383
1384 BotanicalName n_abies_grandis = BotanicalName.NewInstance(Rank.SPECIES());
1385 n_abies_grandis.setNameCache("Abies grandis", true);
1386 Taxon t_abies_grandis = Taxon.NewInstance(n_abies_grandis, sec);
1387 taxonService.save(t_abies_grandis);
1388
1389 BotanicalName n_abies_kawakamii = BotanicalName.NewInstance(Rank.SPECIES());
1390 n_abies_kawakamii.setNameCache("Abies kawakamii", true);
1391 Taxon t_abies_kawakamii = Taxon.NewInstance(n_abies_kawakamii, sec);
1392 t_abies_kawakamii.getTitleCache();
1393 taxonService.save(t_abies_kawakamii);
1394
1395 // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1396 Taxon t_abies_kawakamii_sensu_komarov = Taxon.NewInstance(n_abies_kawakamii, sec_sensu);
1397 taxonService.save(t_abies_kawakamii_sensu_komarov);
1398 t_abies_kawakamii_sensu_komarov.addTaxonRelation(t_abies_balsamea, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null);
1399 taxonService.saveOrUpdate(t_abies_kawakamii_sensu_komarov);
1400
1401 BotanicalName n_abies_lasiocarpa = BotanicalName.NewInstance(Rank.SPECIES());
1402 n_abies_lasiocarpa.setNameCache("Abies lasiocarpa", true);
1403 Taxon t_abies_lasiocarpa = Taxon.NewInstance(n_abies_lasiocarpa, sec);
1404 taxonService.save(t_abies_lasiocarpa);
1405
1406 // add taxa to classifications
1407 europeanAbiesClassification.addChildTaxon(t_abies_balsamea, null, null);
1408 alternativeClassification.addChildTaxon(t_abies_lasiocarpa, null, null);
1409 classificationService.saveOrUpdate(europeanAbiesClassification);
1410 classificationService.saveOrUpdate(alternativeClassification);
1411
1412 //
1413 // Description
1414 //
1415 TaxonDescription d_abies_alba = TaxonDescription.NewInstance(t_abies_alba);
1416 TaxonDescription d_abies_balsamea = TaxonDescription.NewInstance(t_abies_balsamea);
1417
1418 d_abies_alba.setUuid(UUID.fromString(D_ABIES_ALBA_UUID));
1419 d_abies_balsamea.setUuid(UUID.fromString(D_ABIES_BALSAMEA_UUID));
1420
1421
1422 // CommonTaxonName
1423 d_abies_alba.addElement(CommonTaxonName.NewInstance("Wei"+UTF8.SHARP_S+"tanne", Language.GERMAN()));
1424 d_abies_alba.addElement(CommonTaxonName.NewInstance("silver fir", Language.ENGLISH()));
1425 d_abies_alba.addElement(Distribution
1426 .NewInstance(
1427 germany,
1428 PresenceAbsenceTerm.NATIVE()));
1429 d_abies_alba.addElement(Distribution
1430 .NewInstance(
1431 russia,
1432 PresenceAbsenceTerm.ABSENT()));
1433
1434 // TextData
1435 d_abies_balsamea
1436 .addElement(TextData
1437 .NewInstance(
1438 "Die Balsam-Tanne (Abies balsamea) ist eine Pflanzenart aus der Gattung der Tannen (Abies). Sie wächst im nordöstlichen Nordamerika, wo sie sowohl Tief- als auch Bergland besiedelt. Sie gilt als relativ anspruchslos gegenüber dem Standort und ist frosthart. In vielen Teilen des natürlichen Verbreitungsgebietes stellt sie die Klimaxbaumart dar.",
1439 Language.GERMAN(), null));
1440 d_abies_balsamea
1441 .addElement(CommonTaxonName
1442 .NewInstance(
1443 "Balsam-Tanne",
1444 Language.GERMAN(), null));
1445
1446 d_abies_balsamea
1447 .addElement(Distribution
1448 .NewInstance(
1449 canada,
1450 PresenceAbsenceTerm.PRESENT()));
1451
1452 d_abies_balsamea
1453 .addElement(Distribution
1454 .NewInstance(
1455 germany,
1456 PresenceAbsenceTerm.NATIVE()));
1457
1458 d_abies_balsamea
1459 .addElement(TextData
1460 .NewInstance(
1461 TaxonServiceSearchTestUtf8Constants.RUSSIAN_ABIES_ALBA_LONG,
1462 Language.RUSSIAN(), null));
1463 d_abies_balsamea
1464 .addElement(CommonTaxonName
1465 .NewInstance(
1466 TaxonServiceSearchTestUtf8Constants.RUSSIAN_ABIES_ALBA_SHORT,
1467 Language.RUSSIAN(), null));
1468 descriptionService.saveOrUpdate(d_abies_balsamea);
1469
1470 setComplete();
1471 endTransaction();
1472
1473
1474 writeDbUnitDataSetFile(new String[] {
1475 "TAXONBASE", "TAXONNAMEBASE",
1476 "TAXONRELATIONSHIP",
1477 "REFERENCE", "DESCRIPTIONELEMENTBASE", "DESCRIPTIONBASE",
1478 "AGENTBASE", "HOMOTYPICALGROUP",
1479 "CLASSIFICATION", "TAXONNODE",
1480 "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING",
1481 "HIBERNATE_SEQUENCES" // IMPORTANT!!!
1482 });
1483
1484 }
1485
1486 /**
1487 *
1488 */
1489 private void refreshLuceneIndex() {
1490
1491 // commitAndStartNewTransaction(null);
1492 commit();
1493 endTransaction();
1494 indexer.purge(DefaultProgressMonitor.NewInstance());
1495 indexer.reindex(typesToIndex, DefaultProgressMonitor.NewInstance());
1496 startNewTransaction();
1497 // commitAndStartNewTransaction(null);
1498 }
1499
1500 /**
1501 * @param numberOfNew
1502 *
1503 */
1504 private void createRandomTaxonWithCommonName(int numberOfNew) {
1505
1506 logger.debug(String.format("creating %1$s random taxan with CommonName", numberOfNew));
1507
1508 commitAndStartNewTransaction(null);
1509
1510 Reference sec = ReferenceFactory.newBook();
1511 referenceService.save(sec);
1512
1513 for (int i = numberOfNew; i < numberOfNew; i++) {
1514 RandomStringUtils.randomAlphabetic(10);
1515 String radomName = RandomStringUtils.randomAlphabetic(5) + " " + RandomStringUtils.randomAlphabetic(10);
1516 String radomCommonName = RandomStringUtils.randomAlphabetic(10);
1517
1518 BotanicalName name = BotanicalName.NewInstance(Rank.SPECIES());
1519 name.setNameCache(radomName, true);
1520 Taxon taxon = Taxon.NewInstance(name, sec);
1521 taxonService.save(taxon);
1522
1523 TaxonDescription description = TaxonDescription.NewInstance(taxon);
1524 description.addElement(CommonTaxonName.NewInstance(radomCommonName, Language.GERMAN()));
1525 descriptionService.save(description);
1526 }
1527
1528 commitAndStartNewTransaction(null);
1529 }
1530
1531 private <T extends CdmBase> void logSearchResults(Pager<SearchResult<T>> pager, Level level, String[] docFields){
1532 if(level == null){
1533 level = Level.DEBUG;
1534 }
1535 if(logger.isEnabledFor(level)){
1536 StringBuilder b = new StringBuilder();
1537 b.append("\n");
1538 int i = 0;
1539 for(SearchResult sr : pager.getRecords()){
1540
1541 b.append(" ").append(i++).append(" - ");
1542 b.append("score:").append(sr.getScore()).append(", ");
1543
1544 if(docFields != null){
1545 b.append("docs : ");
1546 for(Document doc : sr.getDocs()) {
1547 b.append("<");
1548 for(String f : docFields){
1549 b.append(f).append(":").append(Arrays.toString(doc.getValues(f)));
1550 }
1551 b.append(">");
1552 }
1553 }
1554
1555 CdmBase entity = sr.getEntity();
1556 if(entity == null){
1557 b.append("NULL");
1558 } else {
1559 b.append(entity.getClass().getSimpleName()).
1560 append(" [").append(entity.getId()).
1561 append(" | ").append(entity.getUuid()).append("] : ").
1562 append(entity.toString());
1563
1564 }
1565 b.append("\n");
1566 }
1567 logger.log(level, b);
1568 }
1569 }
1570
1571 }