Project

General

Profile

Download (75 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
import org.apache.lucene.queryParser.ParseException;
32
import org.junit.Assert;
33
import org.junit.Before;
34
import org.junit.Ignore;
35
import org.junit.Test;
36
import org.unitils.dbunit.annotation.DataSet;
37
import org.unitils.spring.annotation.SpringBeanByType;
38

    
39
import eu.etaxonomy.cdm.api.cache.MockCdmCacher;
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.AbsenceTerm;
54
import eu.etaxonomy.cdm.model.description.CategoricalData;
55
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
56
import eu.etaxonomy.cdm.model.description.DescriptionBase;
57
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
58
import eu.etaxonomy.cdm.model.description.Distribution;
59
import eu.etaxonomy.cdm.model.description.Feature;
60
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
61
import eu.etaxonomy.cdm.model.description.PresenceTerm;
62
import eu.etaxonomy.cdm.model.description.State;
63
import eu.etaxonomy.cdm.model.description.StateData;
64
import eu.etaxonomy.cdm.model.description.TaxonDescription;
65
import eu.etaxonomy.cdm.model.description.TextData;
66
import eu.etaxonomy.cdm.model.location.Country;
67
import eu.etaxonomy.cdm.model.location.NamedArea;
68
import eu.etaxonomy.cdm.model.name.BotanicalName;
69
import eu.etaxonomy.cdm.model.name.NonViralName;
70
import eu.etaxonomy.cdm.model.name.Rank;
71
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
72
import eu.etaxonomy.cdm.model.reference.Reference;
73
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
74
import eu.etaxonomy.cdm.model.taxon.Classification;
75
import eu.etaxonomy.cdm.model.taxon.Synonym;
76
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
77
import eu.etaxonomy.cdm.model.taxon.Taxon;
78
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
79
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
80
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
81
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
82
import eu.etaxonomy.cdm.persistence.query.MatchMode;
83
import eu.etaxonomy.cdm.persistence.query.OrderHint;
84
import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
85
import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
86

    
87

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

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

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

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

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

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

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

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

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

    
111

    
112

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

    
128
    private static final int BENCHMARK_ROUNDS = 300;
129

    
130
    private Set<Class<? extends CdmBase>> typesToIndex = null;
131

    
132
    private NamedArea germany;
133
    private NamedArea france ;
134
    private NamedArea russia ;
135
    private NamedArea canada ;
136

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

    
147
        germany =  Country.GERMANY();
148
        france = Country.FRANCEFRENCHREPUBLIC();
149
        russia = Country.RUSSIANFEDERATION();
150
        canada = Country.CANADA();
151
        
152
		// Have to add a mock cdm cacher since the disabling of transactions
153
		// results in the default CdmCacher object not working due to the fact that 
154
		// the current session for the CdmGenericDaoImpl.findByUuidWithoutFlush in
155
		// the autowired CdmDaoCacher is null
156
		// Comment out the line below to see the error.
157
        MockCdmCacher cdmCacher = new MockCdmCacher();
158

    
159
    }
160

    
161
    @Test
162
    public void testDbUnitUsageTest() throws Exception {
163
        assertNotNull("taxonService should exist", taxonService);
164
        assertNotNull("nameService should exist", nameService);
165
    }
166

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

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

    
185
        Pager<IdentifiableEntity> pager = taxonService.findTaxaAndNames(configurator);
186
        List<IdentifiableEntity> list = pager.getRecords();
187

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

    
203
        logger.debug("number of taxa: " + list.size());
204
        assertEquals(8, list.size());
205

    
206
        // pass 2
207
//        configurator.setDoTaxaByCommonNames(false);
208
//        configurator.setDoMisappliedNames(true);
209
//        configurator.setClassification(classificationService.load(UUID.fromString(CLASSIFICATION_UUID)));
210
//        pager = taxonService.findTaxaAndNames(configurator);
211
//        list = pager.getRecords();
212
//        assertEquals(0, list.size());
213

    
214
    }
215

    
216
    /**
217
     * Test method for
218
     * {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#searchTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.Reference)}
219
     * .
220
     */
221
    @Test
222
    @DataSet
223
    public final void testSearchTaxaByName() {
224
        logger.warn("testSearchTaxaByName not yet implemented"); // TODO
225
    }
226

    
227
    @SuppressWarnings("rawtypes")
228
    @Test
229
    @DataSet
230
    public final void testPurgeIndex() throws CorruptIndexException, IOException, ParseException {
231

    
232
        refreshLuceneIndex();
233

    
234
        Pager<SearchResult<TaxonBase>> pager;
235

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

    
239
        indexer.purge(null);
240
        commitAndStartNewTransaction(null);
241

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

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

    
252
        refreshLuceneIndex();
253

    
254
        Pager<SearchResult<TaxonBase>> pager;
255

    
256
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"tanne", null, null, null,
257
                false, null, null, null, null);
258
        Assert.assertEquals("Expecting one entity when searching for CommonTaxonName", Integer.valueOf(1),
259
                pager.getCount());
260

    
261
        // the description containing the Nulltanne has no taxon attached,
262
        // taxon.id = null
263
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Nulltanne", null, null, null,
264
                false, null, null, null, null);
265
        Assert.assertEquals("Expecting no entity when searching for 'Nulltanne' ", Integer.valueOf(0), pager.getCount());
266

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

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

    
275
    }
276

    
277
    @SuppressWarnings("rawtypes")
278
    @Test
279
    @DataSet
280
    public final void testFindByDescriptionElementFullText_Distribution() throws CorruptIndexException, IOException, ParseException {
281

    
282
        refreshLuceneIndex();
283

    
284
        Pager<SearchResult<TaxonBase>> pager;
285
        // by Area
286
        pager = taxonService.findByDescriptionElementFullText(null, "Canada", null, null, null, false, null, null, null, null);
287
        Assert.assertEquals("Expecting one entity when searching for arae 'Canada'", Integer.valueOf(1), pager.getCount());
288
        // by Status
289
        pager = taxonService.findByDescriptionElementFullText(null, "present", null, null, null, false, null, null, null, null);
290
        Assert.assertEquals("Expecting one entity when searching for status 'present'", Integer.valueOf(1), pager.getCount());
291
    }
292

    
293
    @SuppressWarnings("rawtypes")
294
    @Test
295
    @DataSet
296
    public final void testFindByDescriptionElementFullText_wildcard() throws CorruptIndexException, IOException, ParseException {
297

    
298
        refreshLuceneIndex();
299

    
300
        Pager<SearchResult<TaxonBase>> pager;
301

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

    
306
    /**
307
     * Regression test for #3113 (hibernate search: wildcard query can cause BooleanQuery$TooManyClauses: maxClauseCount is set to 1024)
308
     *
309
     * @throws CorruptIndexException
310
     * @throws IOException
311
     * @throws ParseException
312
     */
313
    @SuppressWarnings("rawtypes")
314
    @Test
315
    @DataSet
316
    public final void testFindByDescriptionElementFullText_TooManyClauses() throws CorruptIndexException, IOException, ParseException {
317

    
318
        // generate 1024 terms to reproduce the bug
319
        TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
320
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
321
        while(uniqueRandomStrs.size() < 1024){
322
            uniqueRandomStrs.add(RandomStringUtils.random(10, true, false));
323
        }
324
        for(String rndStr: uniqueRandomStrs){
325
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
326
        }
327
        descriptionService.saveOrUpdate(description);
328
        commitAndStartNewTransaction(null);
329

    
330
        refreshLuceneIndex();
331

    
332
        Pager<SearchResult<TaxonBase>> pager;
333

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

    
338
    /**
339
     * Regression test for #3116 (fulltext search: always only one page of results)
340
     *
341
     * @throws CorruptIndexException
342
     * @throws IOException
343
     * @throws ParseException
344
     */
345
    @SuppressWarnings("rawtypes")
346
    @Test
347
    @DataSet    
348
    public final void testFullText_Paging() throws CorruptIndexException, IOException, ParseException {
349

    
350
        Reference sec = ReferenceFactory.newDatabase();
351
        referenceService.save(sec);
352

    
353
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
354
        int numOfItems = 100;
355
        while(uniqueRandomStrs.size() < numOfItems){
356
            uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
357
        }
358

    
359
        for(String rndStr: uniqueRandomStrs){
360

    
361
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SERIES()), sec);
362
            taxon.setTitleCache("Tax" + rndStr, true);
363
            taxonService.save(taxon);
364

    
365
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
366
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
367
            descriptionService.saveOrUpdate(description);
368
        }
369

    
370
        commitAndStartNewTransaction(new String[]{"TAXONBASE"});
371
        refreshLuceneIndex();
372

    
373
        int pageSize = 10;
374

    
375
        Pager<SearchResult<TaxonBase>> pager;
376

    
377
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, null, null, null);
378
        Assert.assertEquals("unexpeted number of pages", Integer.valueOf(numOfItems / pageSize), pager.getPagesAvailable());
379
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 9, null, null);
380
        Assert.assertNotNull("last page must have records", pager.getRecords());
381
        Assert.assertNotNull("last item on last page must exist", pager.getRecords().get(0));
382
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, false, pageSize, 10, null, null);
383
        Assert.assertNotNull("last page + 1 must not have any records", pager.getRecords());
384
    }
385

    
386
    /**
387
     * test for max score and sort by score of hit groups
388
     * with all matches per taxon in a single TextData  element
389
     * see {@link #testFullText_ScoreAndOrder_2()} for the complement
390
     * test with matches in multiple TextData per taxon
391
     *
392
     * @throws CorruptIndexException
393
     * @throws IOException
394
     * @throws ParseException
395
     */
396
    @SuppressWarnings("rawtypes")
397
    @Test
398
    @DataSet
399
    @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
400
    public final void testFullText_ScoreAndOrder_1() throws CorruptIndexException, IOException, ParseException {
401

    
402
        int numOfTaxa = 3;
403

    
404
        UUID[] taxonUuids = new UUID[numOfTaxa];
405
        StringBuilder text = new StringBuilder();
406

    
407
        for(int i = 0; i < numOfTaxa; i++){
408

    
409
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
410
            taxon.setTitleCache("Taxon_" + i, true);
411
            taxonUuids[i] = taxon.getUuid();
412
            taxonService.save(taxon);
413

    
414
            text.append(" ").append("Rot");
415
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
416
            description.addElement(TextData.NewInstance(text.toString(), Language.DEFAULT(), null));
417
            descriptionService.saveOrUpdate(description);
418
        }
419

    
420
        commitAndStartNewTransaction(null);
421
        refreshLuceneIndex();
422

    
423
        Pager<SearchResult<TaxonBase>> pager;
424

    
425
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
426
        for(int i = 0; i < numOfTaxa; i++){
427
            Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
428
        }
429
        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);
430
    }
431

    
432
    /**
433
     * test for max score and sort by score of hit groups
434
     * with all matches per taxon in a multiple TextData elements
435
     * see {@link #testFullText_ScoreAndOrder_1()} for the complement
436
     * test with matches in a single TextData per taxon
437
     *
438
     * @throws CorruptIndexException
439
     * @throws IOException
440
     * @throws ParseException
441
     */
442
    @SuppressWarnings("rawtypes")
443
    @Test
444
    @DataSet
445
    @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
446
    public final void testFullText_ScoreAndOrder_2() throws CorruptIndexException, IOException, ParseException {
447

    
448
        int numOfTaxa = 3;
449

    
450
        UUID[] taxonUuids = new UUID[numOfTaxa];
451

    
452
        for(int i = 0; i < numOfTaxa; i++){
453

    
454
            Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
455
            taxon.setTitleCache("Taxon_" + i, true);
456
            taxonUuids[i] = taxon.getUuid();
457
            taxonService.save(taxon);
458

    
459
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
460
            for(int k = 0; k < i; k++){
461
                description.addElement(TextData.NewInstance("Rot", Language.DEFAULT(), null));
462
            }
463
            descriptionService.saveOrUpdate(description);
464
        }
465

    
466
        commitAndStartNewTransaction(null);
467
        refreshLuceneIndex();
468

    
469
        Pager<SearchResult<TaxonBase>> pager;
470

    
471
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Rot", null, null, null, false, null, null, null, null);
472
        for(int i = 0; i < numOfTaxa; i++){
473
            Assert.assertEquals("taxa should be orderd by relevance (= score)", taxonUuids[numOfTaxa - i - 1], pager.getRecords().get(i).getEntity().getUuid());
474
        }
475
        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);
476
    }
477

    
478

    
479
    /**
480
     * @throws CorruptIndexException
481
     * @throws IOException
482
     * @throws ParseException
483
     * @throws LuceneMultiSearchException
484
     */
485
    @Test
486
    @DataSet
487
    public final void testFullText_Grouping() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
488

    
489
        TaxonDescription description = (TaxonDescription) descriptionService.find(UUID.fromString(D_ABIES_ALBA_UUID));
490
        Set<String> uniqueRandomStrs = new HashSet<String>(1024);
491
        int numOfItems = 100;
492
        while(uniqueRandomStrs.size() < numOfItems){
493
            uniqueRandomStrs.add(RandomStringUtils.random(5, true, false));
494
        }
495
        for(String rndStr: uniqueRandomStrs){
496
            description.addElement(CommonTaxonName.NewInstance("Rot" + rndStr, Language.DEFAULT()));
497
        }
498
        descriptionService.saveOrUpdate(description);
499

    
500
        commitAndStartNewTransaction(new String[]{"DESCRIPTIONELEMENTBASE"});
501

    
502
        refreshLuceneIndex();
503

    
504
        int pageSize = 10;
505

    
506
        Pager<SearchResult<TaxonBase>> pager;
507
        boolean highlightFragments = true;
508

    
509
        // test with findByDescriptionElementFullText
510
        pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Rot*", null, null, null, highlightFragments, pageSize, null, null, null);
511
        logSearchResults(pager, Level.DEBUG, null);
512
        Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
513
        Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
514
        Map<String, String[]> highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
515
        // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
516
        int maxDocsPerGroup = 10;
517
        Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
518

    
519
        // test with findByEverythingFullText
520
        pager = taxonService.findByEverythingFullText( "Rot*", null, null, highlightFragments, pageSize, null, null, null);
521
        logSearchResults(pager, Level.DEBUG, null);
522
        Assert.assertEquals("All matches should be grouped into a single SearchResult element", 1, pager.getRecords().size());
523
        Assert.assertEquals("The count property of the pager must be set correctly", 1, pager.getCount().intValue());
524
        highlightMap = pager.getRecords().get(0).getFieldHighlightMap();
525
        // maxDocsPerGroup is defined in LuceneSearch and defaults to 10
526
        maxDocsPerGroup = 10;
527
        Assert.assertEquals("expecting 10 highlighted fragments of field 'name'", maxDocsPerGroup, highlightMap.get("name").length);
528

    
529
    }
530

    
531
    @SuppressWarnings("rawtypes")
532
    @Test
533
    @DataSet
534
    public final void testFindByDescriptionElementFullText_TextData() throws CorruptIndexException, IOException, ParseException {
535

    
536
        refreshLuceneIndex();
537

    
538
        Pager<SearchResult<TaxonBase>> pager;
539
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, false, null, null, null, null);
540
        logSearchResults(pager, Level.DEBUG, null);
541
        Assert.assertEquals("Expecting one entity when searching for any TextData", Integer.valueOf(1), pager.getCount());
542
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
543
        Assert.assertTrue("Expecting two docs, one for RUSSIAN and one for GERMAN", pager.getRecords().get(0).getDocs().size() == 2);
544
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
545

    
546

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

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

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

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

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

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

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

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

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

    
578
    @SuppressWarnings("rawtypes")
579
    @Test
580
    @DataSet
581
    public final void testFindByDescriptionElementFullText_MultipleWords() throws CorruptIndexException, IOException, ParseException {
582

    
583
        refreshLuceneIndex();
584

    
585
        // Pflanzenart aus der Gattung der Tannen
586

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

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

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

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

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

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

    
606

    
607
    }
608

    
609

    
610
    @SuppressWarnings("rawtypes")
611
    @Test
612
    @DataSet
613
    public final void testFindByDescriptionElementFullText_modify_DescriptionElement() throws CorruptIndexException, IOException, ParseException {
614

    
615
        refreshLuceneIndex();
616

    
617
        Pager<SearchResult<TaxonBase>> pager;
618
        //
619
        // modify the DescriptionElement
620
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
621
        Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
622
        Document indexDocument = pager.getRecords().get(0).getDocs().iterator().next();
623
        String[] descriptionElementUuidStr = indexDocument.getValues("uuid");
624
        String[] inDescriptionUuidStr = indexDocument.getValues("inDescription.uuid");
625
        // is only one uuid!
626
        DescriptionElementBase textData = descriptionService.getDescriptionElementByUuid(UUID.fromString(descriptionElementUuidStr[0]));
627

    
628
        ((TextData)textData).removeText(Language.GERMAN());
629
        ((TextData)textData).putText(Language.SPANISH_CASTILIAN(), "abeto balsámico");
630

    
631
        descriptionService.saveDescriptionElement(textData);
632
        commitAndStartNewTransaction(null);
633
//        printDataSet(System.out, new String[] {
634
//                "DESCRIPTIONELEMENTBASE", "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING" }
635
//        );
636

    
637
        //
638
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Balsam-Tanne", null, null, Arrays.asList(new Language[]{Language.GERMAN(), Language.RUSSIAN()}), false, null, null, null, null);
639
        Assert.assertEquals("The german 'Balsam-Tanne' TextData should no longer be indexed", Integer.valueOf(0), pager.getCount());
640
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
641
        Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto balsámico'", Integer.valueOf(1), pager.getCount());
642
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "balsámico", null, null, null, false, null, null, null, null);
643
        Assert.assertEquals("expecting to find the SPANISH_CASTILIAN 'abeto balsámico'", Integer.valueOf(1), pager.getCount());
644

    
645
        //
646
        // modify the DescriptionElement via the Description object
647
        DescriptionBase<?> description = descriptionService.find(UUID.fromString(inDescriptionUuidStr[0]));
648
        Set<DescriptionElementBase> elements = description.getElements();
649
        for( DescriptionElementBase elm : elements){
650
            if(elm.getUuid().toString().equals(descriptionElementUuidStr[0])){
651
                ((TextData)elm).removeText(Language.SPANISH_CASTILIAN());
652
                ((TextData)elm).putText(Language.POLISH(), "Jodła balsamiczna");
653
            }
654
        }
655
        descriptionService.saveOrUpdate(description);
656
        commitAndStartNewTransaction(null);
657
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "abeto", null, null, Arrays.asList(new Language[]{Language.SPANISH_CASTILIAN()}), false, null, null, null, null);
658
        Assert.assertEquals("The spanish 'abeto balsámico' TextData should no longer be indexed", Integer.valueOf(0), pager.getCount());
659
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "balsamiczna", null, null, Arrays.asList(new Language[]{Language.POLISH()}), false, null, null, null, null);
660
        Assert.assertEquals("expecting to find the POLISH 'Jodła balsamiczna'", Integer.valueOf(1), pager.getCount());
661
    }
662

    
663
    @SuppressWarnings("rawtypes")
664
    @Test
665
    @DataSet
666
    public final void testFindByDescriptionElementFullText_modify_Taxon() throws CorruptIndexException, IOException, ParseException {
667

    
668
        refreshLuceneIndex();
669

    
670
        Pager<SearchResult<TaxonBase>> pager;
671
        Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
672
        TaxonDescription d_abies_balsamea = (TaxonDescription)descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
673

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

    
677
        // exchange the Taxon with another one via the Taxon object
678
        // 1.) remove existing description:
679
        t_abies_balsamea.removeDescription(d_abies_balsamea);
680

    
681
        taxonService.saveOrUpdate(t_abies_balsamea);
682
        commitAndStartNewTransaction(null);
683

    
684
        t_abies_balsamea = (Taxon)taxonService.find(t_abies_balsamea.getUuid());
685

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

    
689
        // 2.) create new description and add to taxon:
690
        TaxonDescription d_abies_balsamea_new = TaxonDescription.NewInstance();
691
        d_abies_balsamea_new
692
                .addElement(TextData
693
                        .NewInstance(
694
                                "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",
695
                                Language.GERMAN(), null));
696
        t_abies_balsamea.addDescription(d_abies_balsamea_new);
697
        // set authorshipCache to null to avoid validation exception,
698
        // this is maybe not needed in future,  see ticket #3344
699
        BotanicalName abies_balsamea = HibernateProxyHelper.deproxy(t_abies_balsamea.getName(), BotanicalName.class);
700
        abies_balsamea.setAuthorshipCache(null);
701
        taxonService.saveOrUpdate(t_abies_balsamea);
702
        commitAndStartNewTransaction(null);
703

    
704
        printDataSet(System.out, new String[] {
705
                "DESCRIPTIONBASE"
706
        });
707

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

    
712
    @SuppressWarnings("rawtypes")
713
    @Test
714
    @DataSet
715
    public final void testFindByDescriptionElementFullText_modify_Classification() throws CorruptIndexException, IOException, ParseException {
716

    
717
        refreshLuceneIndex();
718

    
719
        Pager<SearchResult<TaxonBase>> pager;
720

    
721
        // put taxon into other classification, new taxon node
722
        Classification classification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
723
        Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
724

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

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

    
733
        // check for the right taxon node
734
        TaxonNode childNode = classification.getChildNodes().iterator().next();
735
        Assert.assertEquals("expecting Abies balsamea sec.", childNode.getTaxon().getUuid().toString(), ABIES_BALSAMEA_UUID);
736
        Assert.assertEquals("expecting default classification", childNode.getClassification().getUuid().toString(), CLASSIFICATION_UUID);
737

    
738
        // moving the taxon around
739
        alternateClassification.addChildNode(childNode, null, null);
740
        classificationService.saveOrUpdate(alternateClassification);
741
        commitAndStartNewTransaction(null);
742

    
743
//        printDataSet(System.out, new String[] {
744
//            "TAXONBASE", "TAXONNODE", "CLASSIFICATION"
745
//        });
746

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

    
750
        classification.getChildNodes().clear();
751
        classificationService.saveOrUpdate(classification);
752
        commitAndStartNewTransaction(null);
753

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

    
757
    }
758

    
759
    @SuppressWarnings("rawtypes")
760
    @Test
761
    @DataSet
762
    public final void testFindByDescriptionElementFullText_CategoricalData() throws CorruptIndexException, IOException, ParseException {
763

    
764
        // add CategoricalData
765
        DescriptionBase d_abies_balsamea = descriptionService.find(UUID.fromString(D_ABIES_BALSAMEA_UUID));
766
        // Categorical data
767
        CategoricalData cdata = CategoricalData.NewInstance();
768
        cdata.setFeature(Feature.DESCRIPTION());
769
        State state = State.NewInstance("green", "green", "gn");
770

    
771
        StateData statedata = StateData.NewInstance(state);
772
        statedata.putModifyingText(Language.ENGLISH(), "always, even during winter");
773
        cdata.addStateData(statedata);
774
        d_abies_balsamea.addElement(cdata);
775

    
776
        UUID termUUID = termService.save(state);
777
        descriptionService.save(d_abies_balsamea);
778

    
779
        commitAndStartNewTransaction(null);
780

    
781
//        printDataSet(System.out, new String[] {
782
//                 "STATEDATA", "STATEDATA_DEFINEDTERMBASE", "STATEDATA_LANGUAGESTRING", "LANGUAGESTRING"});
783

    
784
        refreshLuceneIndex();
785

    
786
        Pager<SearchResult<TaxonBase>> pager;
787
        pager = taxonService.findByDescriptionElementFullText(CategoricalData.class, "green", null, null, null, false, null, null, null, null);
788
        Assert.assertEquals("Expecting one entity", Integer.valueOf(1), pager.getCount());
789
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getEntity().getTitleCache());
790
        Assert.assertTrue("Expecting only one doc", pager.getRecords().get(0).getDocs().size() == 1);
791
        Assert.assertEquals("Abies balsamea sec. Kohlbecker, A., Testcase standart views, 2013", pager.getRecords().get(0).getDocs().iterator().next().get("inDescription.taxon.titleCache"));
792

    
793

    
794
        //TODO modify the StateData
795
        TaxonBase taxon = pager.getRecords().get(0).getEntity();
796

    
797
        String newName = "Quercus robur";
798
        taxon.setTitleCache(newName + " sec. ", true);
799

    
800
        taxonService.saveOrUpdate(taxon);
801
        commitAndStartNewTransaction(null);
802

    
803
        taxon = taxonService.find(taxon.getUuid());
804
        Assert.assertEquals(newName + " sec. ", taxon.getTitleCache());
805
        DefinedTermBase term = termService.find(termUUID);
806
        
807
        termService.delete(term);
808
        
809
    }
810

    
811
    @SuppressWarnings("rawtypes")
812
    @Test
813
    @DataSet
814
    public final void testFindByDescriptionElementFullText_Highlighting() throws CorruptIndexException, IOException, ParseException {
815

    
816
        refreshLuceneIndex();
817

    
818
        Pager<SearchResult<TaxonBase>> pager;
819
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Abies", null, null, null, true, null, null, null, null);
820
        Assert.assertEquals("Expecting one entity when searching for any TextData", Integer.valueOf(1), pager.getCount());
821
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
822
        Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
823
        String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
824
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Abies</B>"));
825

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

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

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

    
844
        pager = taxonService.findByDescriptionElementFullText(TextData.class, "Gatt*", null, null, null, true, null, null, null, null);
845
        searchResult = pager.getRecords().get(0);
846
        Assert.assertTrue("Wildcard search : Expecting at least one item in highlighted fragments", searchResult.getFieldHighlightMap().size() > 0);
847
        fragments = searchResult.getFieldHighlightMap().values().iterator().next();
848
        Assert.assertTrue("first fragments should contains serch term", fragments[0].contains("<B>Gatt"));
849
    }
850

    
851

    
852
    @Test
853
    @DataSet
854
    public final void testFindByFullText() throws CorruptIndexException, IOException, ParseException {
855

    
856
        refreshLuceneIndex();
857

    
858
        Classification europeanAbiesClassification = classificationService.find(UUID.fromString(CLASSIFICATION_UUID));
859

    
860
        Pager<SearchResult<TaxonBase>> pager;
861

    
862
        pager = taxonService.findByFullText(null, "Abies", null, null, true, null, null, null, null); // --> 7
863
        logSearchResults(pager, Level.DEBUG, null);
864
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
865

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

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

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

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

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

    
881
        // synonym in classification ???
882
    }
883

    
884
    @Test
885
    @DataSet
886
    public final void testPrepareByAreaSearch() throws IOException, ParseException {
887

    
888
        List<PresenceAbsenceTermBase<?>> statusFilter = new ArrayList<PresenceAbsenceTermBase<?>>();
889
        List<NamedArea> areaFilter = new ArrayList<NamedArea>();
890
        areaFilter.add(germany);
891
        areaFilter.add(canada);
892
        areaFilter.add(russia);
893

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

    
897
    }
898

    
899
    @Test
900
    @DataSet
901
    public final void testFindTaxaAndNamesByFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
902

    
903
        refreshLuceneIndex();
904

    
905
        Pager<SearchResult<TaxonBase>> pager;
906

    
907
        Classification alternateClassification = classificationService.find(UUID.fromString(CLASSIFICATION_ALT_UUID));
908

    
909

    
910
        pager = taxonService.findTaxaAndNamesByFullText(
911
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
912
                "Abies", null, null, null, null, true, null, null, null, null);
913
//        logPagerRecords(pager, Level.DEBUG);
914
        Assert.assertEquals("doTaxa & doSynonyms", Integer.valueOf(8), pager.getCount());
915

    
916
        pager = taxonService.findTaxaAndNamesByFullText(
917
                EnumSet.allOf(TaxaAndNamesSearchMode.class),
918
                "Abies", null, null, null, null, true, null, null, null, null);
919
//        logPagerRecords(pager, Level.DEBUG);
920
        Assert.assertEquals("all search modes", Integer.valueOf(8), pager.getCount());
921

    
922
        pager = taxonService.findTaxaAndNamesByFullText(
923
                EnumSet.allOf(TaxaAndNamesSearchMode.class),
924
                "Abies", alternateClassification, null, null, null, true, null, null, null, null);
925
//        logPagerRecords(pager, Level.DEBUG);
926
        Assert.assertEquals("all search modes, filtered by alternateClassification", Integer.valueOf(1), pager.getCount());
927

    
928
        pager = taxonService.findTaxaAndNamesByFullText(
929
                EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
930
                "Abies", null, null, null, null, true, null, null, null, null);
931
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
932
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
933
        Assert.assertEquals(Synonym.class, searchResult.getEntity().getClass());
934
        // Abies subalpina sec. Kohlbecker, A., Testcase standart views, 2013
935

    
936

    
937
        pager = taxonService.findTaxaAndNamesByFullText(
938
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
939
                "Abies", null, null, null, null, true, null, null, null, null);
940
        Assert.assertEquals("Expecting 0 entity", Integer.valueOf(0), pager.getCount());
941

    
942

    
943
        pager = taxonService.findTaxaAndNamesByFullText(
944
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
945
                "Tanne", null, null, null, null, true, null, null, null, null);
946
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), Integer.valueOf(pager.getRecords().size()));
947
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
948

    
949
        pager = taxonService.findTaxaAndNamesByFullText(
950
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
951
                "kawakamii", null, null, null, null, true, null, null, null, null);
952
        logSearchResults(pager, Level.DEBUG, null);
953
        Assert.assertEquals("Expecting 1 entity", Integer.valueOf(1), pager.getCount());
954

    
955
    }
956

    
957
    @Test
958
    @DataSet
959
    public final void testFindTaxaAndNamesByFullText_Sort() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
960

    
961
        refreshLuceneIndex();
962

    
963
        Pager<SearchResult<TaxonBase>> pager;
964

    
965
        List<OrderHint> orderHints = new ArrayList<OrderHint>();
966

    
967
        String[] docFields2log = new String[]{"id"};
968

    
969
        // SortById
970
        orderHints.addAll(OrderHint.ORDER_BY_ID);
971
        pager = taxonService.findTaxaAndNamesByFullText(
972
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
973
                "Abies", null, null, null, null, true, null, null, orderHints, null);
974
//        logSearchResults(pager, Level.DEBUG, docFields2log);
975
        int lastId = -1;
976
        for(SearchResult<TaxonBase> rs : pager.getRecords()){
977
            if(lastId != -1){
978
                Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
979
            }
980
            lastId = rs.getEntity().getId();
981
        }
982

    
983
        orderHints.addAll(OrderHint.ORDER_BY_ID);
984
        pager = taxonService.findTaxaAndNamesByFullText(
985
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
986
                "Abies", null, null, null, null, true, null, null, orderHints, null);
987
//        logSearchResults(pager, Level.DEBUG, docFields2log);
988

    
989
        lastId = -1;
990
        for(SearchResult<TaxonBase> rs : pager.getRecords()){
991
            if(lastId != -1){
992
                Assert.assertTrue("results not sorted by id", lastId < rs.getEntity().getId());
993
            }
994
            lastId = rs.getEntity().getId();
995
        }
996

    
997
        // Sortby NOMENCLATURAL_SORT_ORDER TODO make assertions !!!
998
        orderHints.clear();
999
        orderHints.addAll(OrderHint.NOMENCLATURAL_SORT_ORDER);
1000
        pager = taxonService.findTaxaAndNamesByFullText(
1001
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1002
                "Abies", null, null, null, null, true, null, null, orderHints, null);
1003
        logSearchResults(pager, Level.DEBUG, null);
1004

    
1005
    }
1006

    
1007
    @Test
1008
    @DataSet
1009
    public final void testFindTaxaAndNamesByFullText_AreaFilter() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1010

    
1011
        refreshLuceneIndex();
1012

    
1013
        Pager<SearchResult<TaxonBase>> pager;
1014

    
1015
        Set<NamedArea> a_germany_canada_russia = new HashSet<NamedArea>();
1016
        a_germany_canada_russia.add(germany);
1017
        a_germany_canada_russia.add(canada);
1018
        a_germany_canada_russia.add(russia);
1019

    
1020
        Set<NamedArea> a_russia = new HashSet<NamedArea>();
1021
        a_russia.add(russia);
1022

    
1023
        Set<PresenceAbsenceTermBase<?>> present = new HashSet<PresenceAbsenceTermBase<?>>();
1024
        present.add(PresenceTerm.PRESENT());
1025

    
1026
        Set<PresenceAbsenceTermBase<?>> present_native = new HashSet<PresenceAbsenceTermBase<?>>();
1027
        present_native.add(PresenceTerm.PRESENT());
1028
        present_native.add(PresenceTerm.NATIVE());
1029

    
1030
        Set<PresenceAbsenceTermBase<?>> absent = new HashSet<PresenceAbsenceTermBase<?>>();
1031
        absent.add(AbsenceTerm.ABSENT());
1032

    
1033
        pager = taxonService.findTaxaAndNamesByFullText(
1034
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa),
1035
                "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1036
        logSearchResults(pager, Level.DEBUG, null);
1037
        Assert.assertEquals("taxa with matching area filter", Integer.valueOf(2), pager.getCount());
1038

    
1039
        // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1040
        pager = taxonService.findTaxaAndNamesByFullText(
1041
                EnumSet.of(TaxaAndNamesSearchMode.doSynonyms),
1042
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1043
        Assert.assertEquals("synonyms with matching area filter", Integer.valueOf(1), pager.getCount());
1044

    
1045
        pager = taxonService.findTaxaAndNamesByFullText(
1046
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1047
                "Abies", null, a_germany_canada_russia, null, null, true, null, null, null, null);
1048
        logSearchResults(pager, Level.DEBUG, null);
1049
        Assert.assertEquals("taxa and synonyms with matching area filter", Integer.valueOf(3), pager.getCount());
1050

    
1051
        pager = taxonService.findTaxaAndNamesByFullText(
1052
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1053
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1054
        Assert.assertEquals("taxa and synonyms with matching area & status filter 1", Integer.valueOf(3), pager.getCount());
1055

    
1056
        pager = taxonService.findTaxaAndNamesByFullText(
1057
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1058
                "Abies", null, a_germany_canada_russia, present, null, true, null, null, null, null);
1059
        Assert.assertEquals("taxa and synonyms with matching area & status filter 2", Integer.valueOf(2), pager.getCount());
1060

    
1061
        pager = taxonService.findTaxaAndNamesByFullText(
1062
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1063
                "Abies", null, a_russia, present, null, true, null, null, null, null);
1064
        Assert.assertEquals("taxa and synonyms with non matching area & status filter", Integer.valueOf(0), pager.getCount());
1065

    
1066
        pager = taxonService.findTaxaAndNamesByFullText(
1067
                EnumSet.of(TaxaAndNamesSearchMode.doTaxaByCommonNames),
1068
                "Tanne", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1069
        Assert.assertEquals("ByCommonNames with area filter", Integer.valueOf(1), pager.getCount());
1070

    
1071
        // abies_kawakamii_sensu_komarov as misapplied name for t_abies_balsamea
1072
        pager = taxonService.findTaxaAndNamesByFullText(
1073
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1074
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1075
        Assert.assertEquals("misappliedNames with matching area & status filter", Integer.valueOf(1), pager.getCount());
1076

    
1077

    
1078
        // 1. remove existing taxon relation
1079
        Taxon t_abies_balsamea = (Taxon)taxonService.find(UUID.fromString(ABIES_BALSAMEA_UUID));
1080
        Set<TaxonRelationship> relsTo = t_abies_balsamea.getRelationsToThisTaxon();
1081
        Assert.assertEquals(Integer.valueOf(1), Integer.valueOf(relsTo.size()));
1082
        TaxonRelationship taxonRelation = relsTo.iterator().next();
1083
        t_abies_balsamea.removeTaxonRelation(taxonRelation);
1084
        taxonService.saveOrUpdate(t_abies_balsamea);
1085
        commitAndStartNewTransaction(null);
1086

    
1087
        pager = taxonService.findTaxaAndNamesByFullText(
1088
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1089
                "Abies", null, a_germany_canada_russia, present_native, null, true, null, null, null, null);
1090
        Assert.assertEquals("misappliedNames with matching area & status filter, should match nothing now", Integer.valueOf(0), pager.getCount());
1091

    
1092
        // 2. now add abies_kawakamii_sensu_komarov as misapplied name for t_abies_alba and search for misapplications in russia: ABSENT
1093
        Taxon t_abies_kawakamii_sensu_komarov = (Taxon)taxonService.find(UUID.fromString(D_ABIES_KAWAKAMII_SEC_KOMAROV_UUID));
1094
        Taxon t_abies_alba = (Taxon)taxonService.find(UUID.fromString(ABIES_ALBA_UUID));
1095
        t_abies_alba.addMisappliedName(t_abies_kawakamii_sensu_komarov, null, null);
1096
        taxonService.update(t_abies_alba);
1097
        commitAndStartNewTransaction(null);
1098

    
1099
        pager = taxonService.findTaxaAndNamesByFullText(
1100
                EnumSet.of(TaxaAndNamesSearchMode.doMisappliedNames),
1101
                "Abies", null, a_germany_canada_russia, absent, null, true, null, null, null, null);
1102
        Assert.assertEquals("misappliedNames with matching area & status filter, should find one", Integer.valueOf(1), pager.getCount());
1103

    
1104
    }
1105

    
1106
    /**
1107
     * Regression test for #3119: fulltext search: Entity always null whatever search
1108
     *
1109
     * @throws CorruptIndexException
1110
     * @throws IOException
1111
     * @throws ParseException
1112
     * @throws LuceneMultiSearchException
1113
     */
1114
    @Test
1115
    @DataSet
1116
    public final void testFindByEverythingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1117

    
1118
        refreshLuceneIndex();
1119

    
1120
        Pager<SearchResult<TaxonBase>> pager;
1121

    
1122
        // via Taxon
1123
        pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1124
        logSearchResults(pager, Level.DEBUG, null);
1125
        Assert.assertTrue("Expecting at least 7 entities for 'Abies'", pager.getCount() > 7);
1126
        Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1127
        Assert.assertEquals("Expecting Taxon entity", Taxon.class, pager.getRecords().get(0).getEntity().getClass());
1128

    
1129
        // via DescriptionElement
1130
        pager = taxonService.findByEverythingFullText("present", null, null, true, null, null, null, null);
1131
        Assert.assertEquals("Expecting one entity when searching for area 'present'", Integer.valueOf(1), pager.getCount());
1132
        Assert.assertNotNull("Expecting entity", pager.getRecords().get(0).getEntity());
1133
        Assert.assertEquals("Expecting Taxon entity", Taxon.class, pager.getRecords().get(0).getEntity().getClass());
1134
        Assert.assertEquals("Expecting Taxon ", ABIES_BALSAMEA_UUID, pager.getRecords().get(0).getEntity().getUuid().toString());
1135

    
1136
    }
1137

    
1138

    
1139
    @Test
1140
    @DataSet
1141
    public final void findByEveryThingFullText() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1142

    
1143
        refreshLuceneIndex();
1144

    
1145
        Pager<SearchResult<TaxonBase>> pager;
1146

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

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

    
1155
        pager = taxonService.findByEverythingFullText("Abies", null, null, true, null, null, null, null);
1156
        Assert.assertEquals("Expecting 8 entities", Integer.valueOf(8), pager.getCount());
1157
        SearchResult<TaxonBase> searchResult = pager.getRecords().get(0);
1158
        Assert.assertTrue("the map of highlighted fragments should contain at least one item", searchResult.getFieldHighlightMap().size() > 0);
1159
        String[] fragments = searchResult.getFieldHighlightMap().values().iterator().next();
1160
        Assert.assertTrue("first fragments should contains serch term", fragments[0].toLowerCase().contains("<b>abies</b>"));
1161
    }
1162

    
1163
//    @SuppressWarnings("rawtypes")
1164
//    @Test
1165
//    @DataSet
1166
//    public final void benchmarkFindTaxaAndNamesHql() throws CorruptIndexException, IOException, ParseException {
1167
//
1168
//        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1169
//
1170
//        IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl();
1171
//        configurator.setTitleSearchString("Weiß%");
1172
//        configurator.setMatchMode(MatchMode.BEGINNING);
1173
//        configurator.setDoTaxa(false);
1174
//        configurator.setDoSynonyms(false);
1175
//        configurator.setDoNamesWithoutTaxa(false);
1176
//        configurator.setDoTaxaByCommonNames(true);
1177
//
1178
//        Pager<IdentifiableEntity> pager;
1179
//
1180
//        long startMillis = System.currentTimeMillis();
1181
//        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1182
//            pager = taxonService.findTaxaAndNames(configurator);
1183
//            if (logger.isDebugEnabled()) {
1184
//                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1185
//            }
1186
//        }
1187
//        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1188
//        logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1189
//    }
1190

    
1191
    @SuppressWarnings("rawtypes")
1192
    @Test
1193
    @DataSet
1194
    public final void benchmarkFindByCommonNameHql() throws CorruptIndexException, IOException, ParseException {
1195

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

    
1198
        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1199

    
1200
        IFindTaxaAndNamesConfigurator configurator = new FindTaxaAndNamesConfiguratorImpl();
1201
        configurator.setTitleSearchString("Wei"+UTF8.SHARP_S+"%");
1202
        configurator.setMatchMode(MatchMode.BEGINNING);
1203
        configurator.setDoTaxa(false);
1204
        configurator.setDoSynonyms(false);
1205
        configurator.setDoNamesWithoutTaxa(false);
1206
        configurator.setDoTaxaByCommonNames(true);
1207

    
1208
        Pager<IdentifiableEntity> pager;
1209

    
1210
        long startMillis = System.currentTimeMillis();
1211
        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1212
            pager = taxonService.findTaxaAndNames(configurator);
1213
            if (logger.isDebugEnabled()) {
1214
                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getTitleCache());
1215
            }
1216
        }
1217
        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1218
        logger.info("Benchmark result - [find taxon by CommonName via HQL] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1219
    }
1220

    
1221
    @SuppressWarnings("rawtypes")
1222
    @Test
1223
    @DataSet
1224
    public final void benchmarkFindByCommonNameLucene() throws CorruptIndexException, IOException, ParseException {
1225

    
1226
        createRandomTaxonWithCommonName(NUM_OF_NEW_RADOM_ENTITIES);
1227

    
1228
        refreshLuceneIndex();
1229

    
1230
        Pager<SearchResult<TaxonBase>> pager;
1231

    
1232
        long startMillis = System.currentTimeMillis();
1233
        for (int indx = 0; indx < BENCHMARK_ROUNDS; indx++) {
1234
            pager = taxonService.findByDescriptionElementFullText(CommonTaxonName.class, "Wei"+UTF8.SHARP_S+"*", null, null, null, false, null, null, null, null);
1235
            if (logger.isDebugEnabled()) {
1236
                logger.debug("[" + indx + "]" + pager.getRecords().get(0).getEntity().getTitleCache());
1237
            }
1238
        }
1239
        double duration = ((double) (System.currentTimeMillis() - startMillis)) / BENCHMARK_ROUNDS;
1240
        logger.info("Benchmark result - [find taxon by CommonName via lucene] : " + duration + "ms (" + BENCHMARK_ROUNDS + " benchmark rounds )");
1241
    }
1242

    
1243
    /**
1244
     * uncomment @Test annotation to create the dataset for this test
1245
     */
1246
//    @Test
1247
    @DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class, value="BlankDataSet.xml")
1248
    public final void createDataSet() throws FileNotFoundException {
1249

    
1250
        Classification europeanAbiesClassification = Classification.NewInstance("European Abies");
1251
        europeanAbiesClassification.setUuid(UUID.fromString(CLASSIFICATION_UUID));
1252
        classificationService.save(europeanAbiesClassification);
1253

    
1254
        Classification alternativeClassification = Classification.NewInstance("Abies alternative");
1255
        alternativeClassification.setUuid(UUID.fromString(CLASSIFICATION_ALT_UUID));
1256
        classificationService.save(alternativeClassification);
1257

    
1258
        Reference<?> sec = ReferenceFactory.newBook();
1259
        sec.setTitleCache("Kohlbecker, A., Testcase standart views, 2013", true);
1260
        Reference<?> sec_sensu = ReferenceFactory.newBook();
1261
        sec_sensu.setTitleCache("Komarov, V. L., Flora SSSR 29", true);
1262
        referenceService.save(sec);
1263
        referenceService.save(sec_sensu);
1264

    
1265
        BotanicalName n_abies = BotanicalName.NewInstance(Rank.GENUS());
1266
        n_abies.setNameCache("Abies", true);
1267
        Taxon t_abies = Taxon.NewInstance(n_abies, sec);
1268
        taxonService.save(t_abies);
1269

    
1270
        BotanicalName n_abies_alba = BotanicalName.NewInstance(Rank.SPECIES());
1271
        n_abies_alba.setNameCache("Abies alba", true);
1272
        Taxon t_abies_alba = Taxon.NewInstance(n_abies_alba, sec);
1273
        t_abies_alba.setUuid(UUID.fromString(ABIES_ALBA_UUID));
1274
        taxonService.save(t_abies_alba);
1275

    
1276
        BotanicalName n_abies_subalpina = BotanicalName.NewInstance(Rank.SPECIES());
1277
        n_abies_subalpina.setNameCache("Abies subalpina", true);
1278
        Synonym s_abies_subalpina = Synonym.NewInstance(n_abies_subalpina, sec);
1279
        taxonService.save(s_abies_subalpina);
1280

    
1281
        BotanicalName n_abies_balsamea = BotanicalName.NewInstance(Rank.SPECIES());
1282
        n_abies_balsamea.setNameCache("Abies balsamea", true);
1283
        Taxon t_abies_balsamea = Taxon.NewInstance(n_abies_balsamea, sec);
1284
        t_abies_balsamea.setUuid(UUID.fromString(ABIES_BALSAMEA_UUID));
1285
        t_abies_balsamea.addSynonym(s_abies_subalpina, SynonymRelationshipType.SYNONYM_OF());
1286
        taxonService.save(t_abies_balsamea);
1287

    
1288
        BotanicalName n_abies_grandis = BotanicalName.NewInstance(Rank.SPECIES());
1289
        n_abies_grandis.setNameCache("Abies grandis", true);
1290
        Taxon t_abies_grandis = Taxon.NewInstance(n_abies_grandis, sec);
1291
        taxonService.save(t_abies_grandis);
1292

    
1293
        BotanicalName n_abies_kawakamii = BotanicalName.NewInstance(Rank.SPECIES());
1294
        n_abies_kawakamii.setNameCache("Abies kawakamii", true);
1295
        Taxon t_abies_kawakamii = Taxon.NewInstance(n_abies_kawakamii, sec);
1296
        t_abies_kawakamii.getTitleCache();
1297
        taxonService.save(t_abies_kawakamii);
1298

    
1299
        // abies_kawakamii_sensu_komarov as missapplied name for t_abies_balsamea
1300
        Taxon t_abies_kawakamii_sensu_komarov = Taxon.NewInstance(n_abies_kawakamii, sec_sensu);
1301
        taxonService.save(t_abies_kawakamii_sensu_komarov);
1302
        t_abies_kawakamii_sensu_komarov.addTaxonRelation(t_abies_balsamea, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null);
1303
        taxonService.saveOrUpdate(t_abies_kawakamii_sensu_komarov);
1304

    
1305
        BotanicalName n_abies_lasiocarpa = BotanicalName.NewInstance(Rank.SPECIES());
1306
        n_abies_lasiocarpa.setNameCache("Abies lasiocarpa", true);
1307
        Taxon t_abies_lasiocarpa = Taxon.NewInstance(n_abies_lasiocarpa, sec);
1308
        taxonService.save(t_abies_lasiocarpa);
1309

    
1310
        // add taxa to classifications
1311
        europeanAbiesClassification.addChildTaxon(t_abies_balsamea, null, null);
1312
        alternativeClassification.addChildTaxon(t_abies_lasiocarpa, null, null);
1313
        classificationService.saveOrUpdate(europeanAbiesClassification);
1314
        classificationService.saveOrUpdate(alternativeClassification);
1315

    
1316
        //
1317
        // Description
1318
        //
1319
        TaxonDescription d_abies_alba = TaxonDescription.NewInstance(t_abies_alba);
1320
        TaxonDescription d_abies_balsamea = TaxonDescription.NewInstance(t_abies_balsamea);
1321

    
1322
        d_abies_alba.setUuid(UUID.fromString(D_ABIES_ALBA_UUID));
1323
        d_abies_balsamea.setUuid(UUID.fromString(D_ABIES_BALSAMEA_UUID));
1324

    
1325

    
1326
        // CommonTaxonName
1327
        d_abies_alba.addElement(CommonTaxonName.NewInstance("Wei"+UTF8.SHARP_S+"tanne", Language.GERMAN()));
1328
        d_abies_alba.addElement(CommonTaxonName.NewInstance("silver fir", Language.ENGLISH()));
1329
        d_abies_alba.addElement(Distribution
1330
                .NewInstance(
1331
                        germany,
1332
                        PresenceTerm.NATIVE()));
1333
        d_abies_alba.addElement(Distribution
1334
                .NewInstance(
1335
                        russia,
1336
                        AbsenceTerm.ABSENT()));
1337

    
1338
        // TextData
1339
        d_abies_balsamea
1340
            .addElement(TextData
1341
                    .NewInstance(
1342
                            "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.",
1343
                            Language.GERMAN(), null));
1344
        d_abies_balsamea
1345
        .addElement(CommonTaxonName
1346
                .NewInstance(
1347
                        "Balsam-Tanne",
1348
                        Language.GERMAN(), null));
1349

    
1350
        d_abies_balsamea
1351
        .addElement(Distribution
1352
                .NewInstance(
1353
                        canada,
1354
                        PresenceTerm.PRESENT()));
1355

    
1356
        d_abies_balsamea
1357
        .addElement(Distribution
1358
                .NewInstance(
1359
                        germany,
1360
                        PresenceTerm.NATIVE()));
1361

    
1362
        d_abies_balsamea
1363
                .addElement(TextData
1364
                        .NewInstance(
1365
                                "Бальзам ньыв (лат. Abies balsamea) – быдма���злӧн пожум котыри�ь ньыв увтырын торь� вид. �ьывпуы� быдмӧ 14–20 метра вылына да овлӧ 10–60 �м кыза диаметрын. �ьывпу панта�ьӧ Ойвыв �мерикаын.",
1366
                                Language.RUSSIAN(), null));
1367
        d_abies_balsamea
1368
        .addElement(CommonTaxonName
1369
                .NewInstance(
1370
                        "Бальзам ньыв",
1371
                        Language.RUSSIAN(), null));
1372
        descriptionService.saveOrUpdate(d_abies_balsamea);
1373

    
1374
        setComplete();
1375
        endTransaction();
1376

    
1377

    
1378
        writeDbUnitDataSetFile(new String[] {
1379
            "TAXONBASE", "TAXONNAMEBASE",
1380
            "SYNONYMRELATIONSHIP", "TAXONRELATIONSHIP",
1381
            "REFERENCE", "DESCRIPTIONELEMENTBASE", "DESCRIPTIONBASE",
1382
            "AGENTBASE", "HOMOTYPICALGROUP",
1383
            "CLASSIFICATION", "TAXONNODE",
1384
            "LANGUAGESTRING", "DESCRIPTIONELEMENTBASE_LANGUAGESTRING",
1385
            "HIBERNATE_SEQUENCES" // IMPORTANT!!!
1386
            });
1387

    
1388
    }
1389

    
1390
    /**
1391
     *
1392
     */
1393
    private void refreshLuceneIndex() {
1394

    
1395
//        commitAndStartNewTransaction(null);
1396
        commit();
1397
        endTransaction();
1398
        indexer.purge(DefaultProgressMonitor.NewInstance());
1399
        indexer.reindex(typesToIndex, DefaultProgressMonitor.NewInstance());
1400
        startNewTransaction();
1401
//        commitAndStartNewTransaction(null);
1402
    }
1403

    
1404
    /**
1405
     * @param numberOfNew
1406
     *
1407
     */
1408
    private void createRandomTaxonWithCommonName(int numberOfNew) {
1409

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

    
1412
        commitAndStartNewTransaction(null);
1413

    
1414
        Reference sec = ReferenceFactory.newBook();
1415
        referenceService.save(sec);
1416

    
1417
        for (int i = numberOfNew; i < numberOfNew; i++) {
1418
            RandomStringUtils.randomAlphabetic(10);
1419
            String radomName = RandomStringUtils.randomAlphabetic(5) + " " + RandomStringUtils.randomAlphabetic(10);
1420
            String radomCommonName = RandomStringUtils.randomAlphabetic(10);
1421

    
1422
            BotanicalName name = BotanicalName.NewInstance(Rank.SPECIES());
1423
            name.setNameCache(radomName, true);
1424
            Taxon taxon = Taxon.NewInstance(name, sec);
1425
            taxonService.save(taxon);
1426

    
1427
            TaxonDescription description = TaxonDescription.NewInstance(taxon);
1428
            description.addElement(CommonTaxonName.NewInstance(radomCommonName, Language.GERMAN()));
1429
            descriptionService.save(description);
1430
        }
1431

    
1432
        commitAndStartNewTransaction(null);
1433
    }
1434

    
1435
    private <T extends CdmBase> void logSearchResults(Pager<SearchResult<T>> pager, Level level, String[] docFields){
1436
        if(level == null){
1437
            level = Level.DEBUG;
1438
        }
1439
        if(logger.isEnabledFor(level)){
1440
            StringBuilder b = new StringBuilder();
1441
            b.append("\n");
1442
            int i = 0;
1443
            for(SearchResult sr : pager.getRecords()){
1444

    
1445
                b.append(" ").append(i++).append(" - ");
1446
                b.append("score:").append(sr.getScore()).append(", ");
1447

    
1448
                if(docFields != null){
1449
                    b.append("docs : ");
1450
                    for(Document doc : sr.getDocs()) {
1451
                        b.append("<");
1452
                        for(String f : docFields){
1453
                            b.append(f).append(":").append(Arrays.toString(doc.getValues(f)));
1454
                        }
1455
                        b.append(">");
1456
                    }
1457
                }
1458

    
1459
                CdmBase entity = sr.getEntity();
1460
                if(entity == null){
1461
                    b.append("NULL");
1462
                } else {
1463
                    b.append(entity.getClass().getSimpleName()).
1464
                        append(" [").append(entity.getId()).
1465
                        append(" | ").append(entity.getUuid()).append("] : ").
1466
                        append(entity.toString());
1467

    
1468
                }
1469
                b.append("\n");
1470
            }
1471
            logger.log(level, b);
1472
        }
1473
    }
1474

    
1475
}
(23-23/27)