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