Project

General

Profile

Download (75.5 KB) Statistics
| Branch: | Tag: | Revision:
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

    
32
import org.apache.lucene.queryparser.classic.ParseException;
33
import org.junit.Assert;
34
import org.junit.Before;
35
import org.junit.Ignore;
36
import org.junit.Test;
37
import org.unitils.dbunit.annotation.DataSet;
38
import org.unitils.spring.annotation.SpringBeanByType;
39

    
40
import eu.etaxonomy.cdm.api.service.config.FindTaxaAndNamesConfiguratorImpl;
41
import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;
42
import eu.etaxonomy.cdm.api.service.pager.Pager;
43
import eu.etaxonomy.cdm.api.service.search.ICdmMassIndexer;
44
import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearchException;
45
import eu.etaxonomy.cdm.api.service.search.SearchResult;
46
import eu.etaxonomy.cdm.common.UTF8;
47
import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor;
48
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
49
import eu.etaxonomy.cdm.model.common.CdmBase;
50
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
51
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
52
import eu.etaxonomy.cdm.model.common.Language;
53
import eu.etaxonomy.cdm.model.description.CategoricalData;
54
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
55
import eu.etaxonomy.cdm.model.description.DescriptionBase;
56
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
57
import eu.etaxonomy.cdm.model.description.Distribution;
58
import eu.etaxonomy.cdm.model.description.Feature;
59
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
60
import eu.etaxonomy.cdm.model.description.State;
61
import eu.etaxonomy.cdm.model.description.StateData;
62
import eu.etaxonomy.cdm.model.description.TaxonDescription;
63
import eu.etaxonomy.cdm.model.description.TextData;
64
import eu.etaxonomy.cdm.model.location.Country;
65
import eu.etaxonomy.cdm.model.location.NamedArea;
66
import eu.etaxonomy.cdm.model.name.BotanicalName;
67
import eu.etaxonomy.cdm.model.name.NonViralName;
68
import eu.etaxonomy.cdm.model.name.Rank;
69
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
70
import eu.etaxonomy.cdm.model.reference.Reference;
71
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
72
import eu.etaxonomy.cdm.model.taxon.Classification;
73
import eu.etaxonomy.cdm.model.taxon.Synonym;
74
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
75
import eu.etaxonomy.cdm.model.taxon.Taxon;
76
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
77
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
78
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
79
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
80
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
81
import eu.etaxonomy.cdm.persistence.query.MatchMode;
82
import eu.etaxonomy.cdm.persistence.query.OrderHint;
83
import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
84
import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
85

    
86
/**
87
 * @author a.babadshanjan, a.kohlbecker
88
 * @created 04.02.2009
89
 */
90
@Ignore
91
public class TaxonServiceSearchTest extends CdmTransactionalIntegrationTest {
92

    
93
    private static final String ABIES_BALSAMEA_UUID = "f65d47bd-4f49-4ab1-bc4a-bc4551eaa1a8";
94

    
95
    private static final String ABIES_ALBA_UUID = "7dbd5810-a3e5-44b6-b563-25152b8867f4";
96

    
97
    private static final String CLASSIFICATION_UUID = "2a5ceebb-4830-4524-b330-78461bf8cb6b";
98

    
99
    private static final String CLASSIFICATION_ALT_UUID = "d7c741e3-ae9e-4a7d-a566-9e3a7a0b51ce";
100

    
101
    private static final String D_ABIES_BALSAMEA_UUID = "900108d8-e6ce-495e-b32e-7aad3099135e";
102

    
103
    private static final String D_ABIES_ALBA_UUID = "ec8bba03-d993-4c85-8472-18b14942464b";
104

    
105
    private static final String D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID = "e9d8c2fd-6409-46d5-9c2e-14a2bbb1b2b1";
106
    private static final int NUM_OF_NEW_RADOM_ENTITIES = 1000;
107

    
108
    private static Logger logger = Logger.getLogger(TaxonServiceSearchTest.class);
109

    
110

    
111

    
112
    @SpringBeanByType
113
    private ITaxonService taxonService;
114
    @SpringBeanByType
115
    private ITermService termService;
116
    @SpringBeanByType
117
    private IClassificationService classificationService;
118
    @SpringBeanByType
119
    private IReferenceService referenceService;
120
    @SpringBeanByType
121
    private IDescriptionService descriptionService;
122
    @SpringBeanByType
123
    private INameService nameService;
124
    @SpringBeanByType
125
    private ICdmMassIndexer indexer;
126

    
127
    @SpringBeanByType
128
    private ITaxonNodeService nodeService;
129

    
130
    private static final int BENCHMARK_ROUNDS = 300;
131

    
132
    private Set<Class<? extends CdmBase>> typesToIndex = null;
133

    
134
    private NamedArea germany;
135
    private NamedArea france ;
136
    private NamedArea russia ;
137
    private NamedArea canada ;
138

    
139
    /**
140
     * @throws java.lang.Exception
141
     */
142
    @Before
143
    public void setUp() throws Exception {
144
        typesToIndex = new HashSet<Class<? extends CdmBase>>();
145
        typesToIndex.add(DescriptionElementBase.class);
146
        typesToIndex.add(TaxonBase.class);
147
        typesToIndex.add(TaxonRelationship.class);
148

    
149
        germany =  Country.GERMANY();
150
        france = Country.FRANCEFRENCHREPUBLIC();
151
        russia = Country.RUSSIANFEDERATION();
152
        canada = Country.CANADA();
153

    
154

    
155
    }
156

    
157
    @Test
158
    public void testDbUnitUsageTest() throws Exception {
159
        assertNotNull("taxonService should exist", taxonService);
160
        assertNotNull("nameService should exist", nameService);
161
    }
162

    
163
    /**
164
     * Test method for
165
     * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator)}
166
     * .
167
     */
168
    @Test
169
    @DataSet
170
    public final void testFindTaxaAndNames() {
171

    
172
        // pass 1
173
        IFindTaxaAndNamesConfigurator<?> configurator = new FindTaxaAndNamesConfiguratorImpl();
174
        configurator.setTitleSearchString("Abies*");
175
        configurator.setMatchMode(MatchMode.BEGINNING);
176
        configurator.setDoTaxa(true);
177
        configurator.setDoSynonyms(true);
178
        configurator.setDoNamesWithoutTaxa(true);
179
        configurator.setDoTaxaByCommonNames(true);
180

    
181
        Pager<IdentifiableEntity> pager = taxonService.findTaxaAndNames(configurator);
182
        List<IdentifiableEntity> list = pager.getRecords();
183

    
184
        if (logger.isDebugEnabled()) {
185
            for (int i = 0; i < list.size(); i++) {
186
                String nameCache = "";
187
                if (list.get(i) instanceof NonViralName) {
188
                    nameCache = ((NonViralName<?>) list.get(i)).getNameCache();
189
                } else if (list.get(i) instanceof TaxonBase) {
190
                    TaxonNameBase<?,?> taxonNameBase = ((TaxonBase) list.get(i)).getName();
191
                    nameCache = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class).getNameCache();
192
                } else {
193
                }
194
                logger.debug(list.get(i).getClass() + "(" + i + ")" + ": Name Cache = " + nameCache + ", Title Cache = "
195
                        + list.get(i).getTitleCache());
196
            }
197
        }
198

    
199
        logger.debug("number of taxa: " + list.size());
200
        assertEquals(9, list.size());
201
        configurator.setTitleSearchString("Balsam-Tanne");
202
        pager = taxonService.findTaxaAndNames(configurator);
203
        list = pager.getRecords();
204
        assertEquals(1, list.size());
205
        // pass 2
206
//        configurator.setDoTaxaByCommonNames(false);
207
//        configurator.setDoMisappliedNames(true);
208
//        configurator.setClassification(classificationService.load(UUID.fromString(CLASSIFICATION_UUID)));
209
//        pager = taxonService.findTaxaAndNames(configurator);
210
//        list = pager.getRecords();
211
//        assertEquals(0, list.size());
212

    
213
    }
214

    
215
    /**
216
     * Test method for
217
     * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#searchTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.Reference)}
218
     * .
219
     */
220
    @Test
221
    @DataSet
222
    public final void testSearchTaxaByName() {
223
         IFindTaxaAndNamesConfigurator<?> configurator = new FindTaxaAndNamesConfiguratorImpl();
224
         configurator.setTitleSearchString("Abies*");
225
         configurator.setMatchMode(MatchMode.BEGINNING);
226
         configurator.setDoTaxa(false);
227
         configurator.setDoSynonyms(false);
228
         configurator.setDoNamesWithoutTaxa(true);
229
         configurator.setDoTaxaByCommonNames(false);
230

    
231
        List<UuidAndTitleCache<IdentifiableEntity>> list = taxonService.findTaxaAndNamesForEditor(configurator);
232

    
233
         Assert.assertEquals("Expecting one entity", 1, list.size());
234

    
235
         configurator.setTitleSearchString("silver fir");
236
         configurator.setMatchMode(MatchMode.BEGINNING);
237
         configurator.setDoTaxa(false);
238
         configurator.setDoSynonyms(false);
239
         configurator.setDoNamesWithoutTaxa(true);
240
         configurator.setDoTaxaByCommonNames(true);
241

    
242
         list = taxonService.findTaxaAndNamesForEditor(configurator);
243

    
244
         Assert.assertEquals("Expecting one entity", 1, list.size());
245

    
246
    }
247

    
248
    @SuppressWarnings("rawtypes")
249
    @Test
250
    @DataSet
251
    public final void testPurgeIndex() throws CorruptIndexException, IOException, ParseException {
252

    
253
        refreshLuceneIndex();
254

    
255
        Pager<SearchResult<TaxonBase>> pager;
256

    
257
        pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 7
258
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
259

    
260
        indexer.purge(null);
261
        commitAndStartNewTransaction(null);
262

    
263
        pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 0
264
        Assert.assertEquals("Expecting no entities since the index has been purged", Integer.valueOf(0), pager.getCount());
265
    }
266

    
267
    @SuppressWarnings("rawtypes")
268
    @Test
269
    @DataSet
270
    public final void testFindByDescriptionElementFullText_CommonName() throws CorruptIndexException, IOException,
271
            ParseException {
272

    
273
        refreshLuceneIndex();
274

    
275
        Pager<SearchResult<TaxonBase>> pager;
276

    
277
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null, null,
278
                false, null, null, null, null);
279
        Assert.assertEquals("Expecting one entity when searching for CommonTaxonName", Integer.valueOf(1),
280
                pager.getCount());
281

    
282
        // the description containing the Nulltanne has no taxon attached,
283
        // taxon.id = null
284
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Nulltanne", null, null, null,
285
                false, null, null, null, null);
286
        Assert.assertEquals("Expecting no entity when searching for 'Nulltanne' ", Integer.valueOf(0), pager.getCount());
287

    
288
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null,
289
                Arrays.asList(new Language[] { Language.GERMAN() }), false, null, null, null, null);
290
        Assert.assertEquals("Expecting one entity when searching in German", Integer.valueOf(1), pager.getCount());
291

    
292
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null,
293
                Arrays.asList(new Language[] { Language.RUSSIAN() }), false, null, null, null, null);
294
        Assert.assertEquals("Expecting no entity when searching in Russian", Integer.valueOf(0), pager.getCount());
295

    
296
    }
297

    
298
    @SuppressWarnings("rawtypes")
299
    @Test
300
    @DataSet
301
    public final void testFindByDescriptionElementFullText_Distribution() throws CorruptIndexException, IOException, ParseException {
302

    
303
        refreshLuceneIndex();
304

    
305
        Pager<SearchResult<TaxonBase>> pager;
306
        // by Area
307
        pager = taxonService.findByDescriptionElementFullText(null, "Canada", null, null, null, false, null, null, null, null);
308
        Assert.assertEquals("Expecting one entity when searching for arae 'Canada'", Integer.valueOf(1), pager.getCount());
309
        // by Status
310
        pager = taxonService.findByDescriptionElementFullText(null, "present", null, null, null, false, null, null, null, null);
311
        Assert.assertEquals("Expecting one entity when searching for status 'present'", Integer.valueOf(1), pager.getCount());
312
    }
313

    
314
    @SuppressWarnings("rawtypes")
315
    @Test
316
    @DataSet
317
    public final void testFindByDescriptionElementFullText_wildcard() throws CorruptIndexException, IOException, ParseException {
318

    
319
        refreshLuceneIndex();
320

    
321
        Pager<SearchResult<TaxonBase>> pager;
322

    
323
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"*", null, null, null, false, null, null, null, null);
324
        Assert.assertEquals("Expecting one entity when searching for CommonTaxonName", Integer.valueOf(1), pager.getCount());
325
    }
326

    
327
    /**
328
     * Regression test for #3113 (hibernate search: wildcard query can cause BooleanQuery$TooManyClauses: maxClauseCount is set to 1024)
329
     *
330
     * @throws CorruptIndexException
331
     * @throws IOException
332
     * @throws ParseException
333
     */
334
    @SuppressWarnings("rawtypes")
335
    @Test
336
    @DataSet
337
    public final void testFindByDescriptionElementFullText_TooManyClauses() throws CorruptIndexException, IOException, ParseException {
338

    
339
        // generate 1024 terms to reproduce the bug
340
        TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
341
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
342
        while(uniqueRandomStrs.size() < 1024){
343
            uniqueRandomStrs.add(RandomStringUtils.random(10, true, false));
344
        }
345
        for(String rndStr: uniqueRandomStrs){
346
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
347
        }
348
        descriptionService.saveOrUpdate(description);
349
        commitAndStartNewTransaction(null);
350

    
351
        refreshLuceneIndex();
352

    
353
        Pager<SearchResult<TaxonBase>> pager;
354

    
355
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, null, null, null, null);
356
        Assert.assertEquals("Expecting all 1024 entities grouped into one SearchResult item when searching for Rot*", 1, pager.getCount().intValue());
357
    }
358

    
359
    /**
360
     * Regression test for #3116 (fulltext search: always only one page of results)
361
     *
362
     * @throws CorruptIndexException
363
     * @throws IOException
364
     * @throws ParseException
365
     */
366
    @SuppressWarnings("rawtypes")
367
    @Test
368
    @DataSet
369
    public final void testFullText_Paging() throws CorruptIndexException, IOException, ParseException {
370

    
371
        Reference sec = ReferenceFactory.newDatabase();
372
        referenceService.save(sec);
373

    
374
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
375
        int numOfItems = 100;
376
        while(uniqueRandomStrs.size() < numOfItems){
377
            uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
378
        }
379

    
380
        for(String rndStr: uniqueRandomStrs){
381

    
382
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SERIES()), sec);
383
            taxon.setTitleCache("Tax" + rndStr, true);
384
            taxonService.save(taxon);
385

    
386
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
387
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
388
            descriptionService.saveOrUpdate(description);
389
        }
390

    
391
        commitAndStartNewTransaction(new String[]{"TAXONBASE"});
392
        refreshLuceneIndex();
393

    
394
        int pageSize = 10;
395

    
396
        Pager<SearchResult<TaxonBase>> pager;
397

    
398
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, null, null, null);
399
        Assert.assertEquals("unexpeted number of pages", Integer.valueOf(numOfItems / pageSize), pager.getPagesAvailable());
400
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 9, null, null);
401
        Assert.assertNotNull("last page must have records", pager.getRecords());
402
        Assert.assertNotNull("last item on last page must exist", pager.getRecords().get(0));
403
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 10, null, null);
404
        Assert.assertNotNull("last page + 1 must not have any records", pager.getRecords());
405
    }
406

    
407
    /**
408
     * test for max score and sort by score of hit groups
409
     * with all matches per taxon in a single TextData  element
410
     * see {@link #testFullText_ScoreAndOrder_2()} for the complement
411
     * test with matches in multiple TextData per taxon
412
     *
413
     * @throws CorruptIndexException
414
     * @throws IOException
415
     * @throws ParseException
416
     */
417
    @SuppressWarnings("rawtypes")
418
    @Test
419
    @DataSet
420
    @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
421
    public final void testFullText_ScoreAndOrder_1() throws CorruptIndexException, IOException, ParseException {
422

    
423
        int numOfTaxa = 3;
424

    
425
        UUID[] taxonUuids = new UUID[numOfTaxa];
426
        StringBuilder text = new StringBuilder();
427

    
428
        for(int i = 0; i < numOfTaxa; i++){
429

    
430
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
431
            taxon.setTitleCache("Taxon_" + i, true);
432
            taxonUuids[i] = taxon.getUuid();
433
            taxonService.save(taxon);
434

    
435
            text.append(" ").append("Rot");
436
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
437
            description.addElement(TextData.NewInstance(text.toString(), Language.DEFAULT(), null));
438
            descriptionService.saveOrUpdate(description);
439
        }
440

    
441
        commitAndStartNewTransaction(null);
442
        refreshLuceneIndex();
443

    
444
        Pager<SearchResult<TaxonBase>> pager;
445

    
446
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
447
        for(int i = 0; i < numOfTaxa; i++){
448
            Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
449
        }
450
        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);
451
    }
452

    
453
    /**
454
     * test for max score and sort by score of hit groups
455
     * with all matches per taxon in a multiple TextData elements
456
     * see {@link #testFullText_ScoreAndOrder_1()} for the complement
457
     * test with matches in a single TextData per taxon
458
     *
459
     * @throws CorruptIndexException
460
     * @throws IOException
461
     * @throws ParseException
462
     */
463
    @SuppressWarnings("rawtypes")
464
    @Test
465
    @DataSet
466
    @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
467
    public final void testFullText_ScoreAndOrder_2() throws CorruptIndexException, IOException, ParseException {
468

    
469
        int numOfTaxa = 3;
470

    
471
        UUID[] taxonUuids = new UUID[numOfTaxa];
472

    
473
        for(int i = 0; i < numOfTaxa; i++){
474

    
475
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
476
            taxon.setTitleCache("Taxon_" + i, true);
477
            taxonUuids[i] = taxon.getUuid();
478
            taxonService.save(taxon);
479

    
480
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
481
            for(int k = 0; k < i; k++){
482
                description.addElement(TextData.NewInstance("Rot", Language.DEFAULT(), null));
483
            }
484
            descriptionService.saveOrUpdate(description);
485
        }
486

    
487
        commitAndStartNewTransaction(null);
488
        refreshLuceneIndex();
489

    
490
        Pager<SearchResult<TaxonBase>> pager;
491

    
492
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
493
        for(int i = 0; i < numOfTaxa; i++){
494
            Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
495
        }
496
        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);
497
    }
498

    
499

    
500
    /**
501
     * @throws CorruptIndexException
502
     * @throws IOException
503
     * @throws ParseException
504
     * @throws LuceneMultiSearchException
505
     */
506
    @Test
507
    @DataSet
508
    public final void testFullText_Grouping() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
509

    
510
        TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
511
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
512
        int numOfItems = 100;
513
        while(uniqueRandomStrs.size() < numOfItems){
514
            uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
515
        }
516
        for(String rndStr: uniqueRandomStrs){
517
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
518
        }
519
        descriptionService.saveOrUpdate(description);
520

    
521
        commitAndStartNewTransaction(new String[]{"DESCRIPTIONELEMENTBASE"});
522

    
523
        refreshLuceneIndex();
524

    
525
        int pageSize = 10;
526

    
527
        Pager<SearchResult<TaxonBase>> pager;
528
        boolean highlightFragments = true;
529

    
530
        // test with findByDescriptionElementFullText
531
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, highlightFragments, pageSize, null, null, null);
532
        logSearchResults(pager, Level.DEBUG, null);
533
        Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
534
        Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
535
        Map<String, String[]> highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
536
        // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
537
        int maxDocsPerGroup = 10;
538
        Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
539

    
540
        // test with findByEverythingFullText
541
        pager = taxonService.findByEverythingFullText( "Rot*", null, null, highlightFragments, pageSize, null, null, null);
542
        logSearchResults(pager, Level.DEBUG, null);
543
        Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
544
        Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
545
        highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
546
        // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
547
        maxDocsPerGroup = 10;
548
        Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
549

    
550
    }
551

    
552
    @SuppressWarnings("rawtypes")
553
    @Test
554
    @DataSet
555
    @Ignore
556
    public final void testFindByDescriptionElementFullText_TextData() throws CorruptIndexException, IOException, ParseException {
557

    
558
        refreshLuceneIndex();
559

    
560
        Pager<SearchResult<TaxonBase>> pager;
561
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, false, null, null, null, null);
562
        logSearchResults(pager, Level.DEBUG, null);
563
        Assert.assertEquals("Expecting one entity when searching for any TextData", Integer.valueOf(1), pager.getCount());
564
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
565
        Assert.assertTrue("Expecting two docs, one for RUSSIAN and one for GERMAN", pager.getRecords().get(0).getDocs().size() == 2);
566
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
567

    
568

    
569
        pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, null, null, false, null, null, null, null);
570
        Assert.assertEquals("Expecting one entity when searching for any type", Integer.valueOf(1), pager.getCount());
571

    
572
        pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.UNKNOWN()}), null, false, null, null, null, null);
573
        Assert.assertEquals("Expecting one entity when searching for any type and for Feature DESCRIPTION", Integer.valueOf(1), pager.getCount());
574

    
575
        pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.CHROMOSOME_NUMBER()}), null, false, null, null, null, null);
576
        Assert.assertEquals("Expecting no entity when searching for any type and for Feature CHROMOSOME_NUMBER", Integer.valueOf(0), pager.getCount());
577

    
578
        pager = taxonService.findByDescriptionElementFullText(null, "Abies", null, Arrays.asList(new Feature[]{Feature.CHROMOSOME_NUMBER(), Feature.UNKNOWN()}), null, false, null, null, null, null);
579
        Assert.assertEquals("Expecting no entity when searching for any type and for Feature DESCRIPTION or CHROMOSOME_NUMBER", Integer.valueOf(1), pager.getCount());
580

    
581
        pager = taxonService.findByDescriptionElementFullText(Distribution.class, "Abies", null, null, null, false, null, null, null, null);
582
        Assert.assertEquals("Expecting no entity when searching for Distribution", Integer.valueOf(0), pager.getCount());
583

    
584
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{}), false, null, null, null, null);
585
        Assert.assertEquals("Expecting one entity", Integer.valueOf(1), pager.getCount());
586
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
587

    
588
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{Language.RUSSIAN()}), false, null, null, null, null);
589
        Assert.assertEquals("Expecting one entity", Integer.valueOf(1), pager.getCount());
590
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
591

    
592
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Бальзам", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
593
        Assert.assertEquals("Expecting no entity", Integer.valueOf(0), pager.getCount());
594

    
595
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
596
        Assert.assertEquals("Expecting one entity", Integer.valueOf(1), pager.getCount());
597
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
598
    }
599

    
600
    @SuppressWarnings("rawtypes")
601
    @Test
602
    @DataSet
603
    public final void testFindByDescriptionElementFullText_MultipleWords() throws CorruptIndexException, IOException, ParseException {
604

    
605
        refreshLuceneIndex();
606

    
607
        // Pflanzenart aus der Gattung der Tannen
608

    
609
        Pager<SearchResult<TaxonBase>> pager;
610
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Tannen", null, null, null, false, null, null, null, null);
611
        Assert.assertEquals("OR search : Expecting one entity", Integer.valueOf(1), pager.getCount());
612

    
613
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Wespen", null, null, null, false, null, null, null, null);
614
        Assert.assertEquals("OR search : Expecting one entity", Integer.valueOf(1), pager.getCount());
615

    
616
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Tannen", null, null, null, false, null, null, null, null);
617
        Assert.assertEquals("AND search : Expecting one entity", Integer.valueOf(1), pager.getCount());
618

    
619
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Wespen", null, null, null, false, null, null, null, null);
620
        Assert.assertEquals("AND search : Expecting no entity", Integer.valueOf(0), pager.getCount());
621

    
622
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Tannen\"", null, null, null, false, null, null, null, null);
623
        Assert.assertEquals("Phrase search : Expecting one entity", Integer.valueOf(1), pager.getCount());
624

    
625
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Wespen\"", null, null, null, false, null, null, null, null);
626
        Assert.assertEquals("Phrase search : Expecting one entity", Integer.valueOf(0), pager.getCount());
627

    
628

    
629
    }
630

    
631

    
632
    @SuppressWarnings("rawtypes")
633
    @Test
634
    @DataSet
635
    public final void testFindByDescriptionElementFullText_modify_DescriptionElement() throws CorruptIndexException, IOException, ParseException {
636

    
637
        refreshLuceneIndex();
638

    
639
        Pager<SearchResult<TaxonBase>> pager;
640
        //
641
        // modify the DescriptionElement
642
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
643
        Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
644
        Document indexDocument = pager.getRecords().get(0).getDocs().iterator().next();
645
        String[] descriptionElementUuidStr = indexDocument.getValues("uuid");
646
        String[] inDescriptionUuidStr = indexDocument.getValues("inDescription.uuid");
647
        // is only one uuid!
648
        DescriptionElementBase textData = descriptionService.getDescriptionElementByUuid(UUID.fromString(descriptionElementUuidStr[0]));
649

    
650
        ((TextData)textData).removeText(Language.GERMAN());
651
        ((TextData)textData).putText(Language.SPANISH_CASTILIAN(), "abeto bals"+UTF8.SMALL_A_ACUTE+"mico");
652

    
653
        descriptionService.saveDescriptionElement(textData);
654
        commitAndStartNewTransaction(null);
655
//        printDataSet(System.out, new String[] {
656
//                "DESCRIPTIONELEMENTBASE", "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING" }
657
//        );
658

    
659
        //
660
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
661
        Assert.assertEquals("The german 'Balsam-Tanne' TextData should no longer be indexed", Integer.valueOf(0), pager.getCount());
662
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
663
        Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico'", Integer.valueOf(1), pager.getCount());
664
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "bals"+UTF8.SMALL_A_ACUTE+"mico", null, null, null, false, null, null, null, null);
665
        Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico'", Integer.valueOf(1), pager.getCount());
666

    
667
        //
668
        // modify the DescriptionElement via the Description object
669
        DescriptionBase<?> description = descriptionService.find(UUID.fromString(inDescriptionUuidStr[0]));
670
        Set<DescriptionElementBase> elements = description.getElements();
671
        for( DescriptionElementBase elm : elements){
672
            if(elm.getUuid().toString().equals(descriptionElementUuidStr[0])){
673
                ((TextData)elm).removeText(Language.SPANISH_CASTILIAN());
674
                ((TextData)elm).putText(Language.POLISH(), "Jod"+UTF8.POLISH_L+"a balsamiczna");
675
            }
676
        }
677
        descriptionService.saveOrUpdate(description);
678
        commitAndStartNewTransaction(null);
679
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
680
        Assert.assertEquals("The spanish 'abeto bals"+UTF8.SMALL_A_ACUTE+"mico' TextData should no longer be indexed", Integer.valueOf(0), pager.getCount());
681
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "balsamiczna", null, null, Arrays.asList(new Language[]{Language.POLISH()}), false, null, null, null, null);
682
        Assert.assertEquals("expecting to find the POLISH 'Jod"+UTF8.POLISH_L+"a balsamiczna'", Integer.valueOf(1), pager.getCount());
683
    }
684

    
685
    @SuppressWarnings("rawtypes")
686
    @Test
687
    @DataSet
688
    public final void testFindByDescriptionElementFullText_modify_Taxon() throws CorruptIndexException, IOException, ParseException {
689

    
690
        refreshLuceneIndex();
691

    
692
        Pager<SearchResult<TaxonBase>> pager;
693
        Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
694
        TaxonDescription d_abies_balsamea = (TaxonDescription)descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
695

    
696
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
697
        Assert.assertEquals("expecting to find the GERMAN 'Balsam-Tanne'", Integer.valueOf(1), pager.getCount());
698

    
699
        // exchange the Taxon with another one via the Taxon object
700
        // 1.) remove existing description:
701
        t_abies_balsamea.removeDescription(d_abies_balsamea);
702

    
703
        taxonService.saveOrUpdate(t_abies_balsamea);
704
        commitAndStartNewTransaction(null);
705

    
706
        t_abies_balsamea = (Taxon)taxonService.find(t_abies_balsamea.getUuid());
707

    
708
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
709
        Assert.assertEquals("'Balsam-Tanne' should no longer be found", Integer.valueOf(0), pager.getCount());
710

    
711
        // 2.) create new description and add to taxon:
712
        TaxonDescription d_abies_balsamea_new = TaxonDescription.NewInstance();
713
        d_abies_balsamea_new
714
                .addElement(TextData
715
                        .NewInstance(
716
                                "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",
717
                                Language.GERMAN(), null));
718
        t_abies_balsamea.addDescription(d_abies_balsamea_new);
719
        // set authorshipCache to null to avoid validation exception,
720
        // this is maybe not needed in future,  see ticket #3344
721
        BotanicalName abies_balsamea = HibernateProxyHelper.deproxy(t_abies_balsamea.getName(), BotanicalName.class);
722
        abies_balsamea.setAuthorshipCache(null);
723
        taxonService.saveOrUpdate(t_abies_balsamea);
724
        commitAndStartNewTransaction(null);
725

    
726
        printDataSet(System.out, new String[] {
727
                "DESCRIPTIONBASE"
728
        });
729

    
730
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "mittelgro"+UTF8.SHARP_S+"er Baum", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
731
        Assert.assertEquals("the taxon should be found via the new Description", Integer.valueOf(1), pager.getCount());
732
    }
733

    
734
    @SuppressWarnings("rawtypes")
735
    @Test
736
    @DataSet
737
    public final void testFindByDescriptionElementFullText_modify_Classification() throws CorruptIndexException, IOException, ParseException {
738

    
739
        refreshLuceneIndex();
740

    
741
        Pager<SearchResult<TaxonBase>> pager;
742

    
743
        // put taxon into other classification, new taxon node
744
        Classification classification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
745
        Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
746

    
747
        // TODO: why is the test failing when the childNode is already retrieved here, and not after the following four lines?
748
        //TaxonNode childNode = classification.getChildNodes().iterator().next();
749

    
750
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
751
        Assert.assertEquals("expecting to find the GERMAN 'Balsam-Tanne' even if filtering by classification", Integer.valueOf(1), pager.getCount());
752
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", alternateClassification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
753
        Assert.assertEquals("GERMAN 'Balsam-Tanne' should NOT be found in other classification", Integer.valueOf(0), pager.getCount());
754

    
755
        // check for the right taxon node
756
        TaxonNode childNode = classification.getChildNodes().iterator().next();
757
        Assert.assertEquals("expecting Abies balsamea sec.", childNode.getTaxon().getUuid().toString(), ABIES_BALSAMEA_UUID);
758
        Assert.assertEquals("expecting default classification", childNode.getClassification().getUuid().toString(), CLASSIFICATION_UUID);
759

    
760
        // moving the taxon around, the rootnode is only a proxy
761
        alternateClassification.setRootNode(HibernateProxyHelper.deproxy(alternateClassification.getRootNode(), TaxonNode.class));
762
        alternateClassification.addChildNode(childNode, null, null);
763

    
764
        classificationService.saveOrUpdate(alternateClassification);
765
        commitAndStartNewTransaction(null);
766

    
767
//        printDataSet(System.out, new String[] {
768
//            "TAXONBASE", "TAXONNODE", "CLASSIFICATION"
769
//        });
770

    
771
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", alternateClassification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
772
        Assert.assertEquals("GERMAN 'Balsam-Tanne' should now be found in other classification", Integer.valueOf(1), pager.getCount());
773

    
774
        classification.getChildNodes().clear();
775
        classificationService.saveOrUpdate(classification);
776
        commitAndStartNewTransaction(null);
777

    
778
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", classification, null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
779
        Assert.assertEquals("Now the GERMAN 'Balsam-Tanne' should NOT be found in original classification", Integer.valueOf(0), pager.getCount());
780

    
781
    }
782

    
783
    @SuppressWarnings("rawtypes")
784
    @Test
785
    @DataSet
786
    public final void testFindByDescriptionElementFullText_CategoricalData() throws CorruptIndexException, IOException, ParseException {
787

    
788
        // add CategoricalData
789
        DescriptionBase d_abies_balsamea = descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
790
        // Categorical data
791
        CategoricalData cdata = CategoricalData.NewInstance();
792
        cdata.setFeature(Feature.DESCRIPTION());
793
        State state = State.NewInstance("green", "green", "gn");
794

    
795
        StateData statedata = StateData.NewInstance(state);
796
        statedata.putModifyingText(Language.ENGLISH(), "always, even during winter");
797
        cdata.addStateData(statedata);
798
        d_abies_balsamea.addElement(cdata);
799

    
800
        UUID termUUID = termService.save(state).getUuid();
801
        descriptionService.save(d_abies_balsamea);
802

    
803
        commitAndStartNewTransaction(null);
804

    
805
//        printDataSet(System.out, new String[] {
806
//                 "STATEDATA", "STATEDATA_DEFINEDTERMBASE", "STATEDATA_LANGUAGESTRING", "LANGUAGESTRING"});
807

    
808
        refreshLuceneIndex();
809

    
810
        Pager<SearchResult<TaxonBase>> pager;
811
        pager = taxonService.findByDescriptionElementFullText(CategoricalData.class, "green", null, null, null, false, null, null, null, null);
812
        Assert.assertEquals("Expecting one entity", Integer.valueOf(1), pager.getCount());
813
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
814
        Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
815
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
816

    
817

    
818
        //TODO modify the StateData
819
        TaxonBase taxon = pager.getRecords().get(0).getEntity();
820

    
821
        String newName = "Quercus robur";
822
        taxon.setTitleCache(newName + " sec. ", true);
823

    
824
        taxonService.saveOrUpdate(taxon);
825
        commitAndStartNewTransaction(null);
826

    
827
        taxon = taxonService.find(taxon.getUuid());
828
        Assert.assertEquals(newName + " sec. ", taxon.getTitleCache());
829
        DefinedTermBase term = termService.find(termUUID);
830

    
831
        termService.delete(term);
832

    
833
    }
834

    
835
    @SuppressWarnings("rawtypes")
836
    @Test
837
    @DataSet
838
    public final void testFindByDescriptionElementFullText_Highlighting() throws CorruptIndexException, IOException, ParseException {
839

    
840
        refreshLuceneIndex();
841

    
842
        Pager<SearchResult<TaxonBase>> pager;
843
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, true, null, null, null, null);
844
        Assert.assertEquals("Expecting one entity when searching for any TextData", Integer.valueOf(1), pager.getCount());
845
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
846
        Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
847
        String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
848
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Abies</B>"));
849

    
850
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Pflanzenart Tannen", null, null, null, true, null, null, null, null);
851
        searchResult = pager.getRecords().get(0);
852
        Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
853
        fragments = searchResult.getFieldHighlightMap().values().iterator().next();
854
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Pflanzenart</B>") || fragments[0].contains("<B>Tannen</B>"));
855

    
856
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "+Pflanzenart +Tannen", null, null, null, true, null, null, null, null);
857
        searchResult = pager.getRecords().get(0);
858
        Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
859
        fragments = searchResult.getFieldHighlightMap().values().iterator().next();
860
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Pflanzenart</B>") && fragments[0].contains("<B>Tannen</B>"));
861

    
862
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "\"Pflanzenart aus der Gattung der Tannen\"", null, null, null, true, null, null, null, null);
863
        searchResult = pager.getRecords().get(0);
864
        Assert.assertTrue("Phrase search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
865
        fragments = searchResult.getFieldHighlightMap().values().iterator().next();
866
        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>"));
867

    
868
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Gatt*", null, null, null, true, null, null, null, null);
869
        searchResult = pager.getRecords().get(0);
870
        Assert.assertTrue("Wildcard search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
871
        fragments = searchResult.getFieldHighlightMap().values().iterator().next();
872
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Gatt"));
873
    }
874

    
875

    
876
    @Test
877
    @DataSet
878
    public final void testFindByFullText() throws CorruptIndexException, IOException, ParseException {
879

    
880
        refreshLuceneIndex();
881

    
882
        Classification europeanAbiesClassification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
883

    
884
        Pager<SearchResult<TaxonBase>> pager;
885

    
886
        pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 7
887
        logSearchResults(pager, Level.DEBUG, null);
888
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
889

    
890
        pager = taxonService.findByFullText(Taxon.class, "Abies", null, null, true, null, null, null, null); // --> 6
891
        Assert.assertEquals("Expecting 7 entities", Integer.valueOf(7), pager.getCount());
892

    
893
        pager = taxonService.findByFullText(Synonym.class, "Abies", null, null, true, null, null, null, null); // --> 1
894
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
895

    
896
        pager = taxonService.findByFullText(TaxonBase.class, "sec", null, null, true, null, null, null, null); // --> 7
897
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
898

    
899
        pager = taxonService.findByFullText(null, "genus", null, null, true, null, null, null, null); // --> 1
900
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
901

    
902
        pager = taxonService.findByFullText(Taxon.class, "subalpina", null, null, true, null, null, null, null); // --> 0
903
        Assert.assertEquals("Expecting 0 entities", Integer.valueOf(0), pager.getCount());
904

    
905
        // synonym in classification ???
906
    }
907

    
908
    @Test
909
    @DataSet
910
    public final void testPrepareByAreaSearch() throws IOException, ParseException {
911

    
912
        List<PresenceAbsenceTerm> statusFilter = new ArrayList<PresenceAbsenceTerm>();
913
        List<NamedArea> areaFilter = new ArrayList<NamedArea>();
914
        areaFilter.add(germany);
915
        areaFilter.add(canada);
916
        areaFilter.add(russia);
917

    
918
        Pager<SearchResult<TaxonBase>> pager = taxonService.findByDistribution(areaFilter, statusFilter, null, 20, 0, null, null);
919
        Assert.assertEquals("Expecting 2 entities", Integer.valueOf(2), Integer.valueOf(pager.getRecords().size()));
920

    
921
    }
922

    
923
    @Test
924
    @DataSet
925
    public final void testFindTaxaAndNamesByFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
926

    
927
        refreshLuceneIndex();
928

    
929
        Pager<SearchResult<TaxonBase>> pager;
930

    
931
        Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
932

    
933

    
934
        pager = taxonService.findTaxaAndNamesByFullText(
935
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
936
                "Abies", null, null, null, null, true, null, null, null, null);
937
//        logPagerRecords(pager, Level.DEBUG);
938
        Assert.assertEquals("doTaxa & doSynonyms", Integer.valueOf(8), pager.getCount());
939

    
940
        pager = taxonService.findTaxaAndNamesByFullText(
941
                EnumSet.allOf(TaxaAndNamesSearchMode.class),
942
                "Abies", null, null, null, null, true, null, null, null, null);
943
//        logPagerRecords(pager, Level.DEBUG);
944
        Assert.assertEquals("all search modes", Integer.valueOf(8), pager.getCount());
945

    
946
        pager = taxonService.findTaxaAndNamesByFullText(
947
                EnumSet.allOf(TaxaAndNamesSearchMode.class),
948
                "Abies", alternateClassification, null, null, null, true, null, null, null, null);
949
//        logPagerRecords(pager, Level.DEBUG);
950
        Assert.assertEquals("all search modes, filtered by alternateClassification", Integer.valueOf(1), pager.getCount());
951

    
952
        pager = taxonService.findTaxaAndNamesByFullText(
953
                EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
954
                "Abies", null, null, null, null, true, null, null, null, null);
955
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
956
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
957
        Assert.assertEquals(Synonym.class, searchResult.getEntity().getClass());
958
        // Abies subalpina sec. Kohlbecker, A., Testcase standart views, 2013
959

    
960

    
961
        pager = taxonService.findTaxaAndNamesByFullText(
962
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
963
                "Abies", null, null, null, null, true, null, null, null, null);
964
        Assert.assertEquals("Expecting 0 entity", Integer.valueOf(0), pager.getCount());
965

    
966

    
967
        pager = taxonService.findTaxaAndNamesByFullText(
968
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
969
                "Tanne", null, null, null, null, true, null, null, null, null);
970
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), Integer.valueOf(pager.getRecords().size()));
971
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
972

    
973
        pager = taxonService.findTaxaAndNamesByFullText(
974
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
975
                "kawakamii", null, null, null, null, true, null, null, null, null);
976
        logSearchResults(pager, Level.DEBUG, null);
977
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
978

    
979
    }
980

    
981
    @Test
982
    @DataSet
983
    public final void testFindTaxaAndNamesByFullText_Sort() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
984

    
985
        refreshLuceneIndex();
986

    
987
        Pager<SearchResult<TaxonBase>> pager;
988

    
989
        List<OrderHint> orderHints = new ArrayList<OrderHint>();
990

    
991
        String[] docFields2log = new String[]{"id"};
992

    
993
        // SortById
994
        orderHints.addAll(OrderHint.ORDER_BY_ID);
995
        pager = taxonService.findTaxaAndNamesByFullText(
996
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
997
                "Abies", null, null, null, null, true, null, null, orderHints, null);
998
//        logSearchResults(pager, Level.DEBUG, docFields2log);
999
        int lastId = -1;
1000
        for(SearchResult<TaxonBase> rs : pager.getRecords()){
1001
            if(lastId != -1){
1002
                Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
1003
            }
1004
            lastId = rs.getEntity().getId();
1005
        }
1006

    
1007
        orderHints.addAll(OrderHint.ORDER_BY_ID);
1008
        pager = taxonService.findTaxaAndNamesByFullText(
1009
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1010
                "Abies", null, null, null, null, true, null, null, orderHints, null);
1011
//        logSearchResults(pager, Level.DEBUG, docFields2log);
1012

    
1013
        lastId = -1;
1014
        for(SearchResult<TaxonBase> rs : pager.getRecords()){
1015
            if(lastId != -1){
1016
                Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
1017
            }
1018
            lastId = rs.getEntity().getId();
1019
        }
1020

    
1021
        // Sortby NOMENCLATURAL_SORT_ORDER TODO make assertions !!!
1022
        orderHints.clear();
1023
        orderHints.addAll(OrderHint.NOMENCLATURAL_SORT_ORDER);
1024
        pager = taxonService.findTaxaAndNamesByFullText(
1025
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1026
                "Abies", null, null, null, null, true, null, null, orderHints, null);
1027
        logSearchResults(pager, Level.DEBUG, null);
1028

    
1029
    }
1030

    
1031
    @Test
1032
    @DataSet
1033
    public final void testFindTaxaAndNamesByFullText_AreaFilter() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1034

    
1035
        refreshLuceneIndex();
1036

    
1037
        Pager<SearchResult<TaxonBase>> pager;
1038

    
1039
        Set<NamedArea> a_germany_canada_russia = new HashSet<NamedArea>();
1040
        a_germany_canada_russia.add(germany);
1041
        a_germany_canada_russia.add(canada);
1042
        a_germany_canada_russia.add(russia);
1043

    
1044
        Set<NamedArea> a_russia = new HashSet<NamedArea>();
1045
        a_russia.add(russia);
1046

    
1047
        Set<PresenceAbsenceTerm> present = new HashSet<PresenceAbsenceTerm>();
1048
        present.add(PresenceAbsenceTerm.PRESENT());
1049

    
1050
        Set<PresenceAbsenceTerm> present_native = new HashSet<PresenceAbsenceTerm>();
1051
        present_native.add(PresenceAbsenceTerm.PRESENT());
1052
        present_native.add(PresenceAbsenceTerm.NATIVE());
1053

    
1054
        Set<PresenceAbsenceTerm> absent = new HashSet<PresenceAbsenceTerm>();
1055
        absent.add(PresenceAbsenceTerm.ABSENT());
1056

    
1057
        pager = taxonService.findTaxaAndNamesByFullText(
1058
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
1059
                "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1060
        logSearchResults(pager, Level.DEBUG, null);
1061
        Assert.assertEquals("taxa with matching area filter", Integer.valueOf(2), pager.getCount());
1062

    
1063
        // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1064
        pager = taxonService.findTaxaAndNamesByFullText(
1065
                EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
1066
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1067
        Assert.assertEquals("synonyms with matching area filter", Integer.valueOf(1), pager.getCount());
1068

    
1069
        pager = taxonService.findTaxaAndNamesByFullText(
1070
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1071
                "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1072
        logSearchResults(pager, Level.DEBUG, null);
1073
        Assert.assertEquals("taxa and synonyms with matching area filter", Integer.valueOf(3), pager.getCount());
1074

    
1075
        pager = taxonService.findTaxaAndNamesByFullText(
1076
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1077
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1078
        Assert.assertEquals("taxa and synonyms with matching area & status filter 1", Integer.valueOf(3), pager.getCount());
1079

    
1080
        pager = taxonService.findTaxaAndNamesByFullText(
1081
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1082
                "Abies", null, a_germany_canada_russia, present, null, true, null, null, null, null);
1083
        Assert.assertEquals("taxa and synonyms with matching area & status filter 2", Integer.valueOf(2), pager.getCount());
1084

    
1085
        pager = taxonService.findTaxaAndNamesByFullText(
1086
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1087
                "Abies", null, a_russia, present, null, true, null, null, null, null);
1088
        Assert.assertEquals("taxa and synonyms with non matching area & status filter", Integer.valueOf(0), pager.getCount());
1089

    
1090
        pager = taxonService.findTaxaAndNamesByFullText(
1091
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
1092
                "Tanne", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1093
        Assert.assertEquals("ByCommonNames with area filter", Integer.valueOf(1), pager.getCount());
1094

    
1095
        // abies_kawakamii_sensu_komarov as misapplied name for t_abies_balsamea
1096
        pager = taxonService.findTaxaAndNamesByFullText(
1097
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1098
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1099
        Assert.assertEquals("misappliedNames with matching area & status filter", Integer.valueOf(1), pager.getCount());
1100

    
1101

    
1102
        // 1. remove existing taxon relation
1103
        Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
1104
        Set<TaxonRelationship> relsTo = t_abies_balsamea.getRelationsToThisTaxon();
1105
        Assert.assertEquals(Integer.valueOf(1), Integer.valueOf(relsTo.size()));
1106
        TaxonRelationship taxonRelation = relsTo.iterator().next();
1107
        t_abies_balsamea.removeTaxonRelation(taxonRelation);
1108
        taxonService.saveOrUpdate(t_abies_balsamea);
1109
        commitAndStartNewTransaction(null);
1110

    
1111
        pager = taxonService.findTaxaAndNamesByFullText(
1112
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1113
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1114
        Assert.assertEquals("misappliedNames with matching area & status filter, should match nothing now", Integer.valueOf(0), pager.getCount());
1115

    
1116
        // 2. now add abies_kawakamii_sensu_komarov as misapplied name for t_abies_alba and search for misapplications in russia: ABSENT
1117
        Taxon t_abies_kawakamii_sensu_komarov = (Taxon)taxonService.find(UUID.fromString(D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID));
1118
        Taxon t_abies_alba = (Taxon)taxonService.find(UUID.fromString(ABIES_ALBA_UUID));
1119
        t_abies_alba.addMisappliedName(t_abies_kawakamii_sensu_komarov, null, null);
1120
        taxonService.update(t_abies_alba);
1121
        commitAndStartNewTransaction(null);
1122

    
1123
        pager = taxonService.findTaxaAndNamesByFullText(
1124
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1125
                "Abies", null, a_germany_canada_russia, absent, null, true, null, null, null, null);
1126
        Assert.assertEquals("misappliedNames with matching area & status filter, should find one", Integer.valueOf(1), pager.getCount());
1127

    
1128
    }
1129

    
1130
    /**
1131
     * Regression test for #3119: fulltext search: Entity always null whatever search
1132
     *
1133
     * @throws CorruptIndexException
1134
     * @throws IOException
1135
     * @throws ParseException
1136
     * @throws LuceneMultiSearchException
1137
     */
1138
    @Test
1139
    @DataSet
1140
    public final void testFindByEverythingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1141

    
1142
        refreshLuceneIndex();
1143

    
1144
        Pager<SearchResult<TaxonBase>> pager;
1145

    
1146
        // via Taxon
1147
        pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1148
        logSearchResults(pager, Level.DEBUG, null);
1149
        Assert.assertTrue("Expecting at least 7 entities for 'Abies'", pager.getCount() > 7);
1150
        Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1151
        Assert.assertEquals("Expecting Taxon entity", Taxon.class, pager.getRecords().get(0).getEntity().getClass());
1152

    
1153
        // via DescriptionElement
1154
        pager = taxonService.findByEverythingFullText("present", null, null, true, null, null, null, null);
1155
        Assert.assertEquals("Expecting one entity when searching for area 'present'", Integer.valueOf(1), pager.getCount());
1156
        Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1157
        Assert.assertEquals("Expecting Taxon entity", Taxon.class, pager.getRecords().get(0).getEntity().getClass());
1158
        Assert.assertEquals("Expecting Taxon ", ABIES_BALSAMEA_UUID, pager.getRecords().get(0).getEntity().getUuid().toString());
1159

    
1160
    }
1161

    
1162

    
1163
    @Test
1164
    @DataSet
1165
    public final void findByEveryThingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1166

    
1167
        refreshLuceneIndex();
1168

    
1169
        Pager<SearchResult<TaxonBase>> pager;
1170

    
1171
        pager = taxonService.findByEverythingFullText("genus", null, null,  false, null, null, null, null); // --> 1
1172
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
1173

    
1174
        //FIXME FAILS: abies balamea is returned twice, see also testFullText_Grouping()
1175
        pager = taxonService.findByEverythingFullText("Balsam-Tanne", null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
1176
        logSearchResults(pager, Level.DEBUG, null);
1177
        Assert.assertEquals("expecting to find the Abies balsamea via the GERMAN DescriptionElements", Integer.valueOf(1), pager.getCount());
1178

    
1179
        pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1180
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
1181
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
1182
        Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
1183
        String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
1184
        Assert.assertTrue("first fragments should contains serch term", fragments[0].toLowerCase().contains("<b>abies</b>"));
1185
    }
1186

    
1187
//    @SuppressWarnings("rawtypes")
1188
//    @Test
1189
//    @DataSet
1190
//    public final void benchmarkFindTaxaAndNamesHql() throws CorruptIndexException, IOException, ParseException {
1191
//
1192
//        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1193
//
1194
//        IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl();
1195
//        configurator.setTitleSearchString("Wei"+UTF8.SHARP_S+"%");
1196
//        configurator.setMatchMode(MatchMode.BEGINNING);
1197
//        configurator.setDoTaxa(false);
1198
//        configurator.setDoSynonyms(false);
1199
//        configurator.setDoNamesWithoutTaxa(false);
1200
//        configurator.setDoTaxaByCommonNames(true);
1201
//
1202
//        Pager<IdentifiableEntity> pager;
1203
//
1204
//        long startMillis = System.currentTimeMillis();
1205
//        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1206
//            pager = taxonService.findTaxaAndNames(configurator);
1207
//            if (logger.isDebugEnabled()) {
1208
//                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1209
//            }
1210
//        }
1211
//        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1212
//        logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1213
//    }
1214

    
1215
    @SuppressWarnings("rawtypes")
1216
    @Test
1217
    @DataSet
1218
    public final void benchmarkFindByCommonNameHql() throws CorruptIndexException, IOException, ParseException {
1219

    
1220
//        printDataSet(System.err, new String[] { "TaxonBase" });
1221

    
1222
        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1223

    
1224
        IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl();
1225
        configurator.setTitleSearchString("Wei"+UTF8.SHARP_S+"%");
1226
        configurator.setMatchMode(MatchMode.BEGINNING);
1227
        configurator.setDoTaxa(false);
1228
        configurator.setDoSynonyms(false);
1229
        configurator.setDoNamesWithoutTaxa(false);
1230
        configurator.setDoTaxaByCommonNames(true);
1231

    
1232
        Pager<IdentifiableEntity> pager;
1233

    
1234
        long startMillis = System.currentTimeMillis();
1235
        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1236
            pager = taxonService.findTaxaAndNames(configurator);
1237
            if (logger.isDebugEnabled()) {
1238
                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1239
            }
1240
        }
1241
        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1242
        logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1243
    }
1244

    
1245
    @SuppressWarnings("rawtypes")
1246
    @Test
1247
    @DataSet
1248
    public final void benchmarkFindByCommonNameLucene() throws CorruptIndexException, IOException, ParseException {
1249

    
1250
        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1251

    
1252
        refreshLuceneIndex();
1253

    
1254
        Pager<SearchResult<TaxonBase>> pager;
1255

    
1256
        long startMillis = System.currentTimeMillis();
1257
        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1258
            pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"*", null, null, null, false, null, null, null, null);
1259
            if (logger.isDebugEnabled()) {
1260
                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getEntity().getTitleCache());
1261
            }
1262
        }
1263
        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1264
        logger.info("Benchmark result - [find taxon by CommonName via lucene] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1265
    }
1266

    
1267
    /**
1268
     * uncomment @Test annotation to create the dataset for this test
1269
     */
1270
    @Override
1271
    //    @Test
1272
    @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="BlankDataSet.xml")
1273
    public final void createTestDataSet() throws FileNotFoundException {
1274

    
1275
        Classification europeanAbiesClassification = Classification.NewInstance("European Abies");
1276
        europeanAbiesClassification.setUuid(UUID.fromString(CLASSIFICATION_UUID));
1277
        classificationService.save(europeanAbiesClassification);
1278

    
1279
        Classification alternativeClassification = Classification.NewInstance("Abies alternative");
1280
        alternativeClassification.setUuid(UUID.fromString(CLASSIFICATION_ALT_UUID));
1281
        classificationService.save(alternativeClassification);
1282

    
1283
        Reference<?> sec = ReferenceFactory.newBook();
1284
        sec.setTitleCache("Kohlbecker, A., Testcase standart views, 2013", true);
1285
        Reference<?> sec_sensu = ReferenceFactory.newBook();
1286
        sec_sensu.setTitleCache("Komarov, V. L., Flora SSSR 29", true);
1287
        referenceService.save(sec);
1288
        referenceService.save(sec_sensu);
1289

    
1290
        BotanicalName n_abies = BotanicalName.NewInstance(Rank.GENUS());
1291
        n_abies.setNameCache("Abies", true);
1292
        Taxon t_abies = Taxon.NewInstance(n_abies, sec);
1293
        taxonService.save(t_abies);
1294

    
1295
        BotanicalName n_abies_alba = BotanicalName.NewInstance(Rank.SPECIES());
1296
        n_abies_alba.setNameCache("Abies alba", true);
1297
        Taxon t_abies_alba = Taxon.NewInstance(n_abies_alba, sec);
1298
        t_abies_alba.setUuid(UUID.fromString(ABIES_ALBA_UUID));
1299
        taxonService.save(t_abies_alba);
1300

    
1301
        BotanicalName n_abies_subalpina = BotanicalName.NewInstance(Rank.SPECIES());
1302
        n_abies_subalpina.setNameCache("Abies subalpina", true);
1303
        Synonym s_abies_subalpina = Synonym.NewInstance(n_abies_subalpina, sec);
1304
        taxonService.save(s_abies_subalpina);
1305

    
1306
        BotanicalName n_abies_balsamea = BotanicalName.NewInstance(Rank.SPECIES());
1307
        n_abies_balsamea.setNameCache("Abies balsamea", true);
1308
        Taxon t_abies_balsamea = Taxon.NewInstance(n_abies_balsamea, sec);
1309
        t_abies_balsamea.setUuid(UUID.fromString(ABIES_BALSAMEA_UUID));
1310
        t_abies_balsamea.addSynonym(s_abies_subalpina, SynonymRelationshipType.SYNONYM_OF());
1311
        taxonService.save(t_abies_balsamea);
1312

    
1313
        BotanicalName n_abies_grandis = BotanicalName.NewInstance(Rank.SPECIES());
1314
        n_abies_grandis.setNameCache("Abies grandis", true);
1315
        Taxon t_abies_grandis = Taxon.NewInstance(n_abies_grandis, sec);
1316
        taxonService.save(t_abies_grandis);
1317

    
1318
        BotanicalName n_abies_kawakamii = BotanicalName.NewInstance(Rank.SPECIES());
1319
        n_abies_kawakamii.setNameCache("Abies kawakamii", true);
1320
        Taxon t_abies_kawakamii = Taxon.NewInstance(n_abies_kawakamii, sec);
1321
        t_abies_kawakamii.getTitleCache();
1322
        taxonService.save(t_abies_kawakamii);
1323

    
1324
        // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1325
        Taxon t_abies_kawakamii_sensu_komarov = Taxon.NewInstance(n_abies_kawakamii, sec_sensu);
1326
        taxonService.save(t_abies_kawakamii_sensu_komarov);
1327
        t_abies_kawakamii_sensu_komarov.addTaxonRelation(t_abies_balsamea, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null);
1328
        taxonService.saveOrUpdate(t_abies_kawakamii_sensu_komarov);
1329

    
1330
        BotanicalName n_abies_lasiocarpa = BotanicalName.NewInstance(Rank.SPECIES());
1331
        n_abies_lasiocarpa.setNameCache("Abies lasiocarpa", true);
1332
        Taxon t_abies_lasiocarpa = Taxon.NewInstance(n_abies_lasiocarpa, sec);
1333
        taxonService.save(t_abies_lasiocarpa);
1334

    
1335
        // add taxa to classifications
1336
        europeanAbiesClassification.addChildTaxon(t_abies_balsamea, null, null);
1337
        alternativeClassification.addChildTaxon(t_abies_lasiocarpa, null, null);
1338
        classificationService.saveOrUpdate(europeanAbiesClassification);
1339
        classificationService.saveOrUpdate(alternativeClassification);
1340

    
1341
        //
1342
        // Description
1343
        //
1344
        TaxonDescription d_abies_alba = TaxonDescription.NewInstance(t_abies_alba);
1345
        TaxonDescription d_abies_balsamea = TaxonDescription.NewInstance(t_abies_balsamea);
1346

    
1347
        d_abies_alba.setUuid(UUID.fromString(D_ABIES_ALBA_UUID));
1348
        d_abies_balsamea.setUuid(UUID.fromString(D_ABIES_BALSAMEA_UUID));
1349

    
1350

    
1351
        // CommonTaxonName
1352
        d_abies_alba.addElement(CommonTaxonName.NewInstance("Wei"+UTF8.SHARP_S+"tanne", Language.GERMAN()));
1353
        d_abies_alba.addElement(CommonTaxonName.NewInstance("silver fir", Language.ENGLISH()));
1354
        d_abies_alba.addElement(Distribution
1355
                .NewInstance(
1356
                        germany,
1357
                        PresenceAbsenceTerm.NATIVE()));
1358
        d_abies_alba.addElement(Distribution
1359
                .NewInstance(
1360
                        russia,
1361
                        PresenceAbsenceTerm.ABSENT()));
1362

    
1363
        // TextData
1364
        d_abies_balsamea
1365
            .addElement(TextData
1366
                    .NewInstance(
1367
                            "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.",
1368
                            Language.GERMAN(), null));
1369
        d_abies_balsamea
1370
        .addElement(CommonTaxonName
1371
                .NewInstance(
1372
                        "Balsam-Tanne",
1373
                        Language.GERMAN(), null));
1374

    
1375
        d_abies_balsamea
1376
        .addElement(Distribution
1377
                .NewInstance(
1378
                        canada,
1379
                        PresenceAbsenceTerm.PRESENT()));
1380

    
1381
        d_abies_balsamea
1382
        .addElement(Distribution
1383
                .NewInstance(
1384
                        germany,
1385
                        PresenceAbsenceTerm.NATIVE()));
1386

    
1387
        d_abies_balsamea
1388
                .addElement(TextData
1389
                        .NewInstance(
1390
                                TaxonServiceSearchTestUtf8Constants.RUSSIAN_ABIES_ALBA_LONG,
1391
                                Language.RUSSIAN(), null));
1392
        d_abies_balsamea
1393
        .addElement(CommonTaxonName
1394
                .NewInstance(
1395
                        TaxonServiceSearchTestUtf8Constants.RUSSIAN_ABIES_ALBA_SHORT,
1396
                        Language.RUSSIAN(), null));
1397
        descriptionService.saveOrUpdate(d_abies_balsamea);
1398

    
1399
        setComplete();
1400
        endTransaction();
1401

    
1402

    
1403
        writeDbUnitDataSetFile(new String[] {
1404
            "TAXONBASE", "TAXONNAMEBASE",
1405
            "SYNONYMRELATIONSHIP", "TAXONRELATIONSHIP",
1406
            "REFERENCE", "DESCRIPTIONELEMENTBASE", "DESCRIPTIONBASE",
1407
            "AGENTBASE", "HOMOTYPICALGROUP",
1408
            "CLASSIFICATION", "TAXONNODE",
1409
            "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING",
1410
            "HIBERNATE_SEQUENCES" // IMPORTANT!!!
1411
            });
1412

    
1413
    }
1414

    
1415
    /**
1416
     *
1417
     */
1418
    private void refreshLuceneIndex() {
1419

    
1420
//        commitAndStartNewTransaction(null);
1421
        commit();
1422
        endTransaction();
1423
        indexer.purge(DefaultProgressMonitor.NewInstance());
1424
        indexer.reindex(typesToIndex, DefaultProgressMonitor.NewInstance());
1425
        startNewTransaction();
1426
//        commitAndStartNewTransaction(null);
1427
    }
1428

    
1429
    /**
1430
     * @param numberOfNew
1431
     *
1432
     */
1433
    private void createRandomTaxonWithCommonName(int numberOfNew) {
1434

    
1435
        logger.debug(String.format("creating %1$s random taxan with CommonName", numberOfNew));
1436

    
1437
        commitAndStartNewTransaction(null);
1438

    
1439
        Reference sec = ReferenceFactory.newBook();
1440
        referenceService.save(sec);
1441

    
1442
        for (int i = numberOfNew; i < numberOfNew; i++) {
1443
            RandomStringUtils.randomAlphabetic(10);
1444
            String radomName = RandomStringUtils.randomAlphabetic(5) + " " + RandomStringUtils.randomAlphabetic(10);
1445
            String radomCommonName = RandomStringUtils.randomAlphabetic(10);
1446

    
1447
            BotanicalName name = BotanicalName.NewInstance(Rank.SPECIES());
1448
            name.setNameCache(radomName, true);
1449
            Taxon taxon = Taxon.NewInstance(name, sec);
1450
            taxonService.save(taxon);
1451

    
1452
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
1453
            description.addElement(CommonTaxonName.NewInstance(radomCommonName, Language.GERMAN()));
1454
            descriptionService.save(description);
1455
        }
1456

    
1457
        commitAndStartNewTransaction(null);
1458
    }
1459

    
1460
    private <T extends CdmBase> void logSearchResults(Pager<SearchResult<T>> pager, Level level, String[] docFields){
1461
        if(level == null){
1462
            level = Level.DEBUG;
1463
        }
1464
        if(logger.isEnabledFor(level)){
1465
            StringBuilder b = new StringBuilder();
1466
            b.append("\n");
1467
            int i = 0;
1468
            for(SearchResult sr : pager.getRecords()){
1469

    
1470
                b.append(" ").append(i++).append(" - ");
1471
                b.append("score:").append(sr.getScore()).append(", ");
1472

    
1473
                if(docFields != null){
1474
                    b.append("docs : ");
1475
                    for(Document doc : sr.getDocs()) {
1476
                        b.append("<");
1477
                        for(String f : docFields){
1478
                            b.append(f).append(":").append(Arrays.toString(doc.getValues(f)));
1479
                        }
1480
                        b.append(">");
1481
                    }
1482
                }
1483

    
1484
                CdmBase entity = sr.getEntity();
1485
                if(entity == null){
1486
                    b.append("NULL");
1487
                } else {
1488
                    b.append(entity.getClass().getSimpleName()).
1489
                        append(" [").append(entity.getId()).
1490
                        append(" | ").append(entity.getUuid()).append("] : ").
1491
                        append(entity.toString());
1492

    
1493
                }
1494
                b.append("\n");
1495
            }
1496
            logger.log(level, b);
1497
        }
1498
    }
1499

    
1500
}
(26-26/31)