Project

General

Profile

« Previous | Next » 

Revision 8311a989

Added by Katja Luther over 7 years ago

fix #6296: include the common name search into the search query of taxa and synonyms

View differences:

cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/taxon/TaxonDaoHibernateImpl.java
134 134
    public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, String queryString, MatchMode matchMode,
135 135
            Integer pageSize, Integer pageNumber) {
136 136

  
137
        return getTaxaByName(doTaxa, doSynonyms, false, false, queryString, null, matchMode, null, null, pageSize, pageNumber, null);
137
        return getTaxaByName(doTaxa, doSynonyms, false, false, false, queryString, null, matchMode, null, null, pageSize, pageNumber, null);
138 138
    }
139 139

  
140 140
    @Override
......
153 153
    }
154 154

  
155 155
    @Override
156
    public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,
156
    public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames,
157 157
            boolean includeAuthors,
158 158
            String queryString, Classification classification,
159 159
            MatchMode matchMode, Set<NamedArea> namedAreas, NameSearchOrder order,
......
162 162
        boolean doCount = false;
163 163

  
164 164
        String searchField = includeAuthors ? "titleCache" : "nameCache";
165
        Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, searchField, queryString, classification, matchMode, namedAreas, order, pageSize, pageNumber, doCount);
165
        Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, doCommonNames, searchField, queryString, classification, matchMode, namedAreas, order, pageSize, pageNumber, doCount);
166 166

  
167 167
        if (query != null){
168 168
            @SuppressWarnings("unchecked")
......
182 182
    //new search for the editor, for performance issues the return values are only uuid and titleCache, to avoid the initialisation of all objects
183 183
    @Override
184 184
    @SuppressWarnings("unchecked")
185
    public List<UuidAndTitleCache<IdentifiableEntity>> getTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, boolean doNamesWithoutTaxa, boolean doMisappliedNames, String queryString, Classification classification,
185
    public List<UuidAndTitleCache<IdentifiableEntity>> getTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, boolean doNamesWithoutTaxa, boolean doMisappliedNames, boolean doCommonNames, String queryString, Classification classification,
186 186
            MatchMode matchMode, Set<NamedArea> namedAreas) {
187 187
//        long zstVorher;
188 188
//        long zstNachher;
......
200 200
        			resultObjects.add(new UuidAndTitleCache(TaxonNameBase.class, name.getUuid(), name.getId(), name.getTitleCache()));
201 201
        		}
202 202
        	}
203
        	if (!doSynonyms && !doTaxa){
203
        	if (!doSynonyms && !doTaxa && !doCommonNames){
204 204
        		return resultObjects;
205 205
        	}
206 206
        }
207
        Query query = prepareTaxaByNameForEditor(doTaxa, doSynonyms, doMisappliedNames, "nameCache", queryString, classification, matchMode, namedAreas, doCount, order);
207
        Query query = prepareTaxaByNameForEditor(doTaxa, doSynonyms, doMisappliedNames, doCommonNames, "nameCache", queryString, classification, matchMode, namedAreas, doCount, order);
208 208

  
209 209

  
210 210
        if (query != null){
......
217 217
                //differentiate taxa and synonyms
218 218
                // new Boolean(result[3].toString()) is due to the fact that result[3] could be a Boolean ora String
219 219
                // see FIXME in 'prepareQuery' for more details
220
                if (doTaxa && doSynonyms){
220
                if (doTaxa || doSynonyms || doCommonNames){
221 221
                    if (result[3].equals("synonym")) {
222 222
                        resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (Integer) result[1], (String)result[2], new Boolean(result[4].toString()), null));
223 223
                    }
224 224
                    else {
225 225
                        resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (Integer) result[1], (String)result[2], new Boolean(result[4].toString()), null));
226 226
                    }
227
                }else if (doTaxa){
228
                        resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (Integer) result[1], (String)result[2], new Boolean(result[4].toString()), null));
227
//                }else if (doTaxa ){
228
//                        resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (Integer) result[1], (String)result[2], new Boolean(result[4].toString()), null));
229 229
                }else if (doSynonyms){
230 230
                    resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (Integer) result[1], (String)result[2], new Boolean(result[4].toString()), null));
231 231
                }
......
268 268
     *
269 269
     *
270 270
     */
271
    private Query prepareTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,
271
    private Query prepareTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames,
272 272
            String searchField, String queryString, Classification classification,
273 273
            MatchMode matchMode, Set<NamedArea> namedAreas, boolean doCount, NameSearchOrder order) {
274
        return prepareQuery(doTaxa, doSynonyms, doMisappliedNames, searchField, queryString,
274
        return prepareQuery(doTaxa, doSynonyms, doMisappliedNames, doCommonNames, searchField, queryString,
275 275
                classification, matchMode, namedAreas, order, doCount, true);
276 276
    }
277 277

  
......
290 290
     * @param clazz
291 291
     * @return
292 292
     */
293
    private Query prepareQuery(boolean doTaxa, boolean doSynonyms, boolean doIncludeMisappliedNames, String searchField, String queryString,
293
    private Query prepareQuery(boolean doTaxa, boolean doSynonyms, boolean doIncludeMisappliedNames, boolean doCommonNames, String searchField, String queryString,
294 294
                Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, NameSearchOrder order, boolean doCount, boolean doNotReturnFullEntities){
295 295

  
296 296
            if (order == null){
......
304 304
                selectWhat = (doCount ? "count(t)": "t");
305 305
            }
306 306

  
307
            /*
308
             *   String what = "select distinct";
309

  
310
        String hql= what + " from Taxon t " +
311
        "join t.descriptions d "+
312
        "join d.descriptionElements e " +
313
        "join e.feature f " +
314
        "where f.supportsCommonTaxonName = true and e.name "+matchMode.getMatchOperator()+" :queryString";//and ls.text like 'common%'";
315

  
316
        Query query = getSession().createQuery(hql);
317

  
318
        query.setParameter("queryString", matchMode.queryStringFrom(queryString));
319

  
320
        if(pageSize != null &&  !doCount) {
321
            query.setMaxResults(pageSize);
322
            if(pageNumber != null) {
323
                query.setFirstResult(pageNumber * pageSize);
324
            }
325
        }
326
        return query;
327
             */
328

  
307 329
            String hql = "";
308 330
            Set<NamedArea> areasExpanded = new HashSet<NamedArea>();
309 331
            if(namedAreas != null && namedAreas.size() > 0){
......
323 345
            String taxonSubselect = subSelects[1];
324 346
            String synonymSubselect = subSelects[2];
325 347
            String misappliedSelect = subSelects[0];
348
            String commonNameSubSelect = subSelects[3];
326 349

  
327 350

  
328 351
            logger.debug("taxonSubselect: " + taxonSubselect != null ? taxonSubselect: "NULL");
......
331 354
            Query subTaxon = null;
332 355
            Query subSynonym = null;
333 356
            Query subMisappliedNames = null;
357
            Query subCommonNames = null;
358

  
334 359
            if(doTaxa){
335 360
                // find Taxa
336 361
                subTaxon = getSession().createQuery(taxonSubselect).setParameter("queryString", hqlQueryString);
......
368 393
                }
369 394
            }
370 395

  
396
            if(doCommonNames){
397
                // find Taxa
398
                subCommonNames = getSession().createQuery(commonNameSubSelect).setParameter("queryString", hqlQueryString);
399

  
400
                if(doAreaRestriction){
401
                    subCommonNames.setParameterList("namedAreasUuids", namedAreasUuids);
402
                }
403
                if(classification != null){
404
                    subCommonNames.setParameter("classification", classification);
405

  
406
                }
407

  
408

  
409
            }
410

  
371 411
            List<Integer> taxa = new ArrayList<Integer>();
372 412
            List<Integer> synonyms = new ArrayList<Integer>();
373 413
            if (doSynonyms){
......
379 419
            if (doIncludeMisappliedNames){
380 420
                taxa.addAll(subMisappliedNames.list());
381 421
            }
422
            if (doCommonNames){
423
                taxa.addAll(subCommonNames.list());
424
            }
382 425

  
383 426
            //FIXME : the fourth element of the result should be a boolean, but in the case of a synonym
384 427
            // (which does require a check) a constant boolean (false) value needs to set. It seems that
......
422 465
                } else{
423 466
                    hql = "select " + selectWhat + " from %s t";
424 467
                }
425
            } else if(doTaxa){
468
            } else if(doTaxa || doCommonNames){
426 469
                if  (taxa.size()>0){
427 470
                    hql = "select " + selectWhat;
428 471
                    // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
......
552 595
     *
553 596
     * FIXME implement classification restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}
554 597
     */
555
    private Query prepareTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, String searchField, String queryString,
598
    private Query prepareTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames, String searchField, String queryString,
556 599
            Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, NameSearchOrder order, Integer pageSize, Integer pageNumber, boolean doCount) {
557 600

  
558
        Query query = prepareQuery(doTaxa, doSynonyms, doMisappliedNames, searchField, queryString, classification, matchMode, namedAreas, order, doCount, false);
601
        Query query = prepareQuery(doTaxa, doSynonyms, doMisappliedNames, doCommonNames, searchField, queryString, classification, matchMode, namedAreas, order, doCount, false);
559 602

  
560 603
        if(pageSize != null &&  !doCount && query != null) {
561 604
            query.setMaxResults(pageSize);
......
570 613
    private Query prepareTaxaByCommonName(String queryString, Classification classification,
571 614
            MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount, boolean doNotReturnFullEntities){
572 615

  
573
        String what = "select";
616
        String what = "select distinct";
574 617
        if (doNotReturnFullEntities){
575 618
        	what += " t.uuid, t.id, t.titleCache, \'taxon\', case when t.taxonNodes is empty and t.relationsFromThisTaxon is empty and t.relationsToThisTaxon is empty then true else false end ";
576 619
        }else {
......
596 639
    }
597 640

  
598 641
    @Override
599
    public long countTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,
642
    public long countTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames,
600 643
            boolean doIncludeAuthors, String queryString, Classification classification,
601 644
        MatchMode matchMode, Set<NamedArea> namedAreas) {
602 645

  
......
612 655
        */
613 656
        String searchField = doIncludeAuthors ? "titleCache": "nameCache";
614 657

  
615
        Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, searchField, queryString, classification, matchMode, namedAreas, null, null, null, doCount);
658
        Query query = prepareTaxaByName(doTaxa, doSynonyms, doMisappliedNames, doCommonNames, searchField, queryString, classification, matchMode, namedAreas, null, null, null, doCount);
616 659
        if (query != null) {
617 660
            return (Long)query.uniqueResult();
618 661
        }else{
......
701 744
    public List<TaxonBase> findByNameTitleCache(boolean doTaxa, boolean doSynonyms, String queryString, Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, NameSearchOrder order, Integer pageNumber, Integer pageSize, List<String> propertyPaths) {
702 745

  
703 746
        boolean doCount = false;
704
        Query query = prepareTaxaByName(doTaxa, doSynonyms, false, "titleCache", queryString, classification, matchMode, namedAreas, order, pageSize, pageNumber, doCount);
747
        Query query = prepareTaxaByName(doTaxa, doSynonyms, false, false, "titleCache", queryString, classification, matchMode, namedAreas, order, pageSize, pageNumber, doCount);
705 748
        if (query != null){
706 749
            List<TaxonBase> results = query.list();
707 750
            defaultBeanInitializer.initializeAll(results, propertyPaths);
......
1457 1500
                " left join rt.name as n2" +
1458 1501
                " left join rft.type as rtype";
1459 1502

  
1503
           String doCommonNamesJoin =   "join t.descriptions d "+
1504
                   "join d.descriptionElements e " +
1505
                   "join e.feature f ";
1506

  
1507

  
1460 1508
           String doClassificationWhere = " tn.classification = :classification";
1461 1509
           String doClassificationForMisappliedNamesWhere = " tn2 .classification = :classification";
1462 1510

  
1463 1511
           String doAreaRestrictionWhere =  " e.area.uuid in (:namedAreasUuids)";
1512
           String doCommonNamesRestrictionWhere = " f.supportsCommonTaxonName = true and e.name "+matchMode.getMatchOperator()+" :queryString";
1464 1513

  
1465 1514
           String doSearchFieldWhere = "%s." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";
1466 1515

  
......
1469 1518
        String taxonSubselect = null;
1470 1519
        String synonymSubselect = null;
1471 1520
        String misappliedSelect = null;
1521
        String commonNameSubselect = null;
1472 1522

  
1473 1523
        if(classification != null ){
1474 1524
            if (!doIncludeMisappliedNames){
......
1481 1531
                    " WHERE " + doAreaRestrictionWhere +
1482 1532
                    " AND " + doClassificationWhere +
1483 1533
                    " AND " + String.format(doSearchFieldWhere, "sn");
1534
                    commonNameSubselect =  doCommonNamesJoin +
1535
                            " WHERE " +  doAreaRestrictionWhere + " AND " + doClassificationWhere +
1536
                            " AND " + String.format(doSearchFieldWhere, "n")
1537
                            + "AND " + doCommonNamesRestrictionWhere;
1484 1538
                } else {
1485 1539
                    taxonSubselect = String.format(doTaxonSubSelect, "t" )+ doTaxonNameJoin +
1486 1540
                    " WHERE " + doClassificationWhere +
......
1488 1542
                    synonymSubselect = String.format(doTaxonSubSelect, "s" ) + doSynonymNameJoin +
1489 1543
                    " WHERE " + doClassificationWhere +
1490 1544
                    " AND " + String.format(doSearchFieldWhere, "sn");
1545
                    commonNameSubselect =String.format(doTaxonSubSelect, "s" )+ doCommonNamesJoin +
1546
                            " WHERE "+ doAreaRestrictionWhere +
1547
                             " AND " + doClassificationWhere +
1548
                            "AND " + doCommonNamesRestrictionWhere;
1491 1549
                }
1492 1550
            }else{ //misappliedNames included
1493 1551
                if(doAreaRestriction){
1494
                    misappliedSelect = String.format(doAreaRestrictionMisappliedNameSubSelect, "t") + doTaxonNameJoin + doMisappliedNamesJoin +
1552
                    misappliedSelect = String.format(doAreaRestrictionMisappliedNameSubSelect, "t") + doTaxonNameJoin + doMisappliedNamesJoin  +
1495 1553
                    " WHERE " + doAreaRestrictionWhere +
1496 1554
                    " AND " + String.format(doSearchFieldWhere, "n") +
1497 1555
                    " AND " + doClassificationForMisappliedNamesWhere +
......
1503 1561

  
1504 1562
                    synonymSubselect = String.format(doAreaRestrictionSubSelect, "s") + doSynonymNameJoin +
1505 1563
                    " WHERE " + doAreaRestrictionWhere +
1506
                    " AND " + doClassificationWhere + " AND " +  String.format(doSearchFieldWhere, "sn");;
1564
                    " AND " + doClassificationWhere + " AND " +  String.format(doSearchFieldWhere, "sn");
1507 1565

  
1566
                    commonNameSubselect= String.format(doAreaRestrictionSubSelect, "t")+ doCommonNamesJoin +
1567
                            " WHERE " + doAreaRestrictionWhere +
1568
                            " AND "+ doClassificationWhere + "AND " + doCommonNamesRestrictionWhere;
1508 1569
                } else {
1509 1570
                    misappliedSelect = String.format(doTaxonMisappliedNameSubSelect, "t" ) + doTaxonNameJoin + doMisappliedNamesJoin +
1510 1571
                    " WHERE " + String.format(doSearchFieldWhere, "n") +
......
1519 1580
                    " WHERE " + doClassificationWhere +
1520 1581
                    " AND " +  String.format(doSearchFieldWhere, "sn");
1521 1582

  
1583
                    commonNameSubselect= String.format(doTaxonSubSelect, "t")+ doCommonNamesJoin +
1584
                            " WHERE " + doClassificationWhere + "AND " + doCommonNamesRestrictionWhere;
1585

  
1522 1586
                }
1523 1587
            }
1524 1588
        } else {
......
1535 1599
                synonymSubselect = String.format(doAreaRestrictionSubSelect, "s") + doSynonymNameJoin +
1536 1600
                " WHERE " +   doAreaRestrictionWhere +
1537 1601
                " AND " +  String.format(doSearchFieldWhere, "sn");
1602
                commonNameSubselect = String.format(doTaxonSubSelect, "t")+ doCommonNamesJoin +
1603
                        " WHERE " + doAreaRestrictionWhere +
1604
                        "AND " + doCommonNamesRestrictionWhere;
1538 1605

  
1539 1606

  
1540 1607
            } else {
1541 1608
                misappliedSelect = String.format(doTaxonMisappliedNameSubSelect, "t" ) + doTaxonNameJoin + doMisappliedNamesJoin + " WHERE " +  String.format(doSearchFieldWhere, "n") + " AND " + doRelationshipTypeComparison;
1542 1609
                taxonSubselect = String.format(doTaxonSubSelect, "t" ) + doTaxonNameJoin + " WHERE " +  String.format(doSearchFieldWhere, "n");
1543 1610
                synonymSubselect = String.format(doTaxonSubSelect, "s" ) + doSynonymNameJoin + " WHERE " +  String.format(doSearchFieldWhere, "sn");
1611
                commonNameSubselect = String.format(doTaxonSubSelect, "t" ) +doCommonNamesJoin + " WHERE "+  doCommonNamesRestrictionWhere;
1544 1612

  
1545 1613
            }
1546 1614
        }
1547
        String[] result = {misappliedSelect, taxonSubselect, synonymSubselect};
1615
        String[] result = {misappliedSelect, taxonSubselect, synonymSubselect, commonNameSubselect};
1548 1616

  
1549 1617
        return result;
1550 1618
    }
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/taxon/ITaxonDao.java
92 92
     * @param propertyPaths TODO
93 93
     * @return list of found taxa
94 94
     */
95
    public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,
95
    public List<TaxonBase> getTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames,
96 96
            boolean includeAuthors, String queryString, Classification classification,
97 97
            MatchMode matchMode, Set<NamedArea> namedAreas,
98 98
            NameSearchOrder order, Integer pageSize, Integer pageNumber, List<String> propertyPaths);
......
109 109
     * @param propertyPaths
110 110
     * @return
111 111
     */
112
    public long countTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames,
112
    public long countTaxaByName(boolean doTaxa, boolean doSynonyms, boolean doMisappliedNames, boolean doCommonNames,
113 113
            boolean doIncludeAuthors, String queryString, Classification classification,
114 114
            MatchMode matchMode, Set<NamedArea> namedAreas);
115 115

  
......
369 369
    public List<TaxonNameBase> findIdenticalNamesNew(List <String> propertyPaths);
370 370

  
371 371
    public List<UuidAndTitleCache<IdentifiableEntity>> getTaxaByNameForEditor(boolean doTaxa, boolean doSynonyms, boolean doNamesWithoutTaxa,
372
            boolean doMisappliedNames,
372
            boolean doMisappliedNames, boolean doCommonNames,
373 373
            String queryString, Classification classification,
374 374
            MatchMode matchMode, Set<NamedArea> namedAreas);
375 375

  
cdmlib-persistence/src/test/java/eu/etaxonomy/cdm/persistence/dao/hibernate/taxon/TaxonDaoHibernateImplTest.java
219 219
         * Misapplied names should be found regardless of whether they are contained in a classification or not.
220 220
         */
221 221
        //two accepted taxa starting with R in classification "TestBaum"
222
        List<TaxonBase> results = taxonDao.getTaxaByName(true, false, false, false, "R*", classification, MatchMode.BEGINNING, null, null, null, null, null);
222
        List<TaxonBase> results = taxonDao.getTaxaByName(true, false, false, false, false, "R*", classification, MatchMode.BEGINNING, null, null, null, null, null);
223 223
        Assert.assertEquals("There should be 2 Taxa", 2, results.size());
224 224

  
225 225
        //three taxa, 2 accepted and 1 misapplied name starting with R
226
        results = taxonDao.getTaxaByName(true, false, true, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
226
        results = taxonDao.getTaxaByName(true, false, true, false, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
227 227
        Assert.assertEquals("There should be 3 Taxa", 3, results.size());
228 228

  
229 229
        //one synonym has no accepted taxon
230
        results = taxonDao.getTaxaByName(true, true, true, false, "A*", null, MatchMode.BEGINNING, null, null, null, null, null);
230
        results = taxonDao.getTaxaByName(true, true, true, false, false, "A*", null, MatchMode.BEGINNING, null, null, null, null, null);
231 231
        Assert.assertEquals("There should be 11 Taxa",11, results.size());
232 232

  
233 233
        //two accepted taxa in classification and 1 misapplied name with accepted name in classification
234
        results = taxonDao.getTaxaByName(true, true, true, false, "R*", classification, MatchMode.BEGINNING, null, null, null, null, null);
234
        results = taxonDao.getTaxaByName(true, true, true, false, false, "R*", classification, MatchMode.BEGINNING, null, null, null, null, null);
235 235
        Assert.assertEquals("There should be 3 Taxa", 3, results.size());
236 236

  
237 237
        //same as above because all taxa, synonyms and misapplied names starting with R are in the classification
238
        results = taxonDao.getTaxaByName(true, true, true, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
238
        results = taxonDao.getTaxaByName(true, true, true, false, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
239 239
        Assert.assertEquals("There should be 3 Taxa", 3, results.size());
240 240

  
241 241
        //find misapplied names with accepted taxon in the classification, the accepted taxa of two misapplied names are in the classification
242
        results = taxonDao.getTaxaByName(false, false, true, false, "*", classification, MatchMode.BEGINNING, null, null, null, null, null);
242
        results = taxonDao.getTaxaByName(false, false, true, false, false, "*", classification, MatchMode.BEGINNING, null, null, null, null, null);
243 243
        Assert.assertEquals("There should be 2 Taxa", 2, results.size());
244 244

  
245 245
        //find misapplied names beginning with R
246
        results = taxonDao.getTaxaByName(false, false, true, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
246
        results = taxonDao.getTaxaByName(false, false, true, false, false, "R*", null, MatchMode.BEGINNING, null, null, null, null, null);
247 247
        Assert.assertEquals("There should be 1 Taxa", 1, results.size());
248 248

  
249 249
        //find all three misapplied names
250
        results = taxonDao.getTaxaByName(false, false, true, false, "*", null, MatchMode.BEGINNING, null, null, null, null, null);
250
        results = taxonDao.getTaxaByName(false, false, true, false, false, "*", null, MatchMode.BEGINNING, null, null, null, null, null);
251 251
        Assert.assertEquals("There should be 3 Taxa", 3, results.size());
252 252

  
253 253
    }
......
261 261
        Reference sec = referenceDao.findById(1);
262 262
        assert sec != null : "sec must exist";
263 263

  
264
        List<UuidAndTitleCache<IdentifiableEntity>> results = taxonDao.getTaxaByNameForEditor(true, true, false,false,"Acher", null, MatchMode.BEGINNING, null);
264
        List<UuidAndTitleCache<IdentifiableEntity>> results = taxonDao.getTaxaByNameForEditor(true, true, false,false, false, "Acher", null, MatchMode.BEGINNING, null);
265 265
        assertNotNull("getTaxaByName should return a List", results);
266 266
        assertFalse("The list should not be empty", results.isEmpty());
267 267
        assertEquals(4, results.size());
268 268

  
269 269

  
270
        results = taxonDao.getTaxaByNameForEditor(true, true, false, false,"A",null, MatchMode.BEGINNING, null);
270
        results = taxonDao.getTaxaByNameForEditor(true, true, false, false,false,"A",null, MatchMode.BEGINNING, null);
271 271
        assertNotNull("getTaxaByName should return a List", results);
272 272
        assertEquals(7, results.size());
273 273

  
274 274

  
275
        results = taxonDao.getTaxaByNameForEditor(true, false,false, false,"A", null,MatchMode.BEGINNING, null);
275
        results = taxonDao.getTaxaByNameForEditor(true, false,false, false,false, "A", null,MatchMode.BEGINNING, null);
276 276
        assertNotNull("getTaxaByName should return a List", results);
277 277
        assertEquals(5, results.size());
278 278
        assertEquals(results.get(0).getType(), Taxon.class);
279 279

  
280
        results = taxonDao.getTaxaByNameForEditor(false, true,false,false, "A", null,MatchMode.BEGINNING, null);
280
        results = taxonDao.getTaxaByNameForEditor(false, true,false,false, false,"A", null,MatchMode.BEGINNING, null);
281 281
        assertNotNull("getTaxaByName should return a List", results);
282 282
        assertEquals(2, results.size());
283 283
        assertEquals(results.get(0).getType(), Synonym.class);
284 284

  
285
        results = taxonDao.getTaxaByNameForEditor(true, true,false,false,"Aus", null,MatchMode.EXACT,  null);
285
        results = taxonDao.getTaxaByNameForEditor(true, true,false,false,false,"Aus", null,MatchMode.EXACT,  null);
286 286
        assertNotNull("getTaxaByName should return a List", results);
287 287
        assertEquals("Results list should contain one entity",1,results.size());
288 288

  
289
        results = taxonDao.getTaxaByNameForEditor(true, true,true,false,"A", null,MatchMode.BEGINNING,  null);
289
        results = taxonDao.getTaxaByNameForEditor(true, true,true,false,false,"A", null,MatchMode.BEGINNING,  null);
290 290
        assertNotNull("getTaxaByName should return a List", results);
291 291
        assertEquals("Results list should contain one entity", 8, results.size());
292 292

  
......
326 326
        // 1. searching for a taxon (Rethera)
327 327
        //long numberOfTaxa = taxonDao.countTaxaByName(Taxon.class, "Rethera", null, MatchMode.BEGINNING, namedAreas);
328 328

  
329
        List<TaxonBase> results = taxonDao.getTaxaByName(true,false, false, false, "Rethera", null, MatchMode.BEGINNING, namedAreas,
329
        List<TaxonBase> results = taxonDao.getTaxaByName(true,false, false, false, false,"Rethera", null, MatchMode.BEGINNING, namedAreas,
330 330
            null, null, null, null);
331 331
        assertNotNull("getTaxaByName should return a List", results);
332 332
        assertTrue("expected to find two taxa but found "+results.size(), results.size() == 2);
333 333

  
334 334
        // 2. searching for a taxon (Rethera) contained in a specific classification
335
        results = taxonDao.getTaxaByName(true, false, false, false, "Rethera", taxonmicTree, MatchMode.BEGINNING, namedAreas,
335
        results = taxonDao.getTaxaByName(true, false, false, false, false,"Rethera", taxonmicTree, MatchMode.BEGINNING, namedAreas,
336 336
            null, null, null, null);
337 337
        assertNotNull("getTaxaByName should return a List", results);
338 338
        assertTrue("expected to find one taxon but found "+results.size(), results.size() == 1);
339 339

  
340 340

  
341 341
        // 3. searching for Synonyms
342
        results = taxonDao.getTaxaByName(false, true, false, false, "Atropo", null, MatchMode.ANYWHERE, null,
342
        results = taxonDao.getTaxaByName(false, true, false, false, false,"Atropo", null, MatchMode.ANYWHERE, null,
343 343
            null, null, null, null);
344 344
        assertNotNull("getTaxaByName should return a List", results);
345 345
        /*System.err.println(results.get(0).getTitleCache() + " - " +results.get(1).getTitleCache() + " - " +results.get(2).getTitleCache() );
......
350 350
        assertTrue("expected to find three taxa but found "+results.size(), results.size() == 3);
351 351

  
352 352
        // 4. searching for Synonyms
353
        results = taxonDao.getTaxaByName(false, true, false, false, "Atropo", null, MatchMode.BEGINNING, null,
353
        results = taxonDao.getTaxaByName(false, true, false, false, false,"Atropo", null, MatchMode.BEGINNING, null,
354 354
            null, null, null, null);
355 355
        assertNotNull("getTaxaByName should return a List", results);
356 356
        assertTrue("expected to find three taxa but found "+results.size(), results.size() == 3);
357 357

  
358 358

  
359 359
        // 5. searching for a Synonyms and Taxa
360
        results = taxonDao.getTaxaByName(true, true, false, false, "A", null, MatchMode.BEGINNING, namedAreas,
360
        results = taxonDao.getTaxaByName(true, true, false, false, false,"A", null, MatchMode.BEGINNING, namedAreas,
361 361
            null, null, null, null);
362 362
        //only five taxa have a distribution
363 363
        assertNotNull("getTaxaByName should return a List", results);
......
438 438
        int numberOfClassifications = classificationDao.count();
439 439
        List<String> propertyPaths = new ArrayList<>();
440 440
        propertyPaths.add("taxonNodes");
441
        List<TaxonBase> taxa = taxonDao.getTaxaByName(true, true, false, false, "P", null, MatchMode.BEGINNING, null, null, null, null, null);
441
        List<TaxonBase> taxa = taxonDao.getTaxaByName(true, true, false, false, false,"P", null, MatchMode.BEGINNING, null, null, null, null, null);
442 442
        Taxon taxon = (Taxon)taxa.get(0);
443 443
        Set<TaxonNode> nodes = taxon.getTaxonNodes();
444 444
        assertTrue(nodes.size() == 1);
......
479 479
    @Test
480 480
    @DataSet
481 481
    public void testCountTaxaByName() {
482
        long numberOfTaxa = taxonDao.countTaxaByName(true, false, false, false, "A", null, MatchMode.BEGINNING, null);
482
        long numberOfTaxa = taxonDao.countTaxaByName(true, false, false, false,false, "A", null, MatchMode.BEGINNING, null);
483 483
        assertEquals(5, numberOfTaxa);
484
        numberOfTaxa = taxonDao.countTaxaByName(true, false, false, false, "Smerinthus kindermannii", null, MatchMode.EXACT, null);
484
        numberOfTaxa = taxonDao.countTaxaByName(true, false, false, false, false,"Smerinthus kindermannii", null, MatchMode.EXACT, null);
485 485
        assertEquals(1, numberOfTaxa);
486
        numberOfTaxa = taxonDao.countTaxaByName(false, true, false, false, "A", null, MatchMode.BEGINNING, null);
486
        numberOfTaxa = taxonDao.countTaxaByName(false, true, false, false, false,"A", null, MatchMode.BEGINNING, null);
487 487
        assertEquals(2, numberOfTaxa);
488
        numberOfTaxa = taxonDao.countTaxaByName(true, true, false, false, "A", null, MatchMode.BEGINNING, null);
488
        numberOfTaxa = taxonDao.countTaxaByName(true, true, false, false, false,"A", null, MatchMode.BEGINNING, null);
489 489
        assertEquals(7, numberOfTaxa);
490
        numberOfTaxa = taxonDao.countTaxaByName(true, true, false, false, "Aasfwerfwf fffe", null, MatchMode.BEGINNING, null);
490
        numberOfTaxa = taxonDao.countTaxaByName(true, true, false, false,false, "Aasfwerfwf fffe", null, MatchMode.BEGINNING, null);
491 491
        assertEquals(0, numberOfTaxa);
492 492
//	FIXME implement test for search in specific classification
493 493
//		Reference reference = referenceDao.findByUuid(UUID.fromString("596b1325-be50-4b0a-9aa2-3ecd610215f2"));
......
1093 1093
        assertFalse("the list should not be empty", commonNameResults.isEmpty());
1094 1094
        assertEquals("There should be one Taxon with common name", 1,commonNameResults.size());
1095 1095
        assertEquals(" sec. ???", ((TaxonBase)commonNameResults.get(0)).getTitleCache());
1096

  
1097
        List<UuidAndTitleCache<IdentifiableEntity>> list = taxonDao.getTaxaByCommonNameForEditor("common%", null, MatchMode.BEGINNING, null);
1098

  
1099
        assertNotNull("getTaxaByCommonName should return a list", commonNameResults);
1100
        assertFalse("the list should not be empty", commonNameResults.isEmpty());
1101
        assertEquals("There should be one Taxon with common name", 1,commonNameResults.size());
1102
        assertEquals(" sec. ???", ((TaxonBase)commonNameResults.get(0)).getTitleCache());
1096 1103
    }
1097 1104

  
1098 1105
    @Test
cdmlib-persistence/src/test/resources/eu/etaxonomy/cdm/persistence/dao/hibernate/taxon/TaxonDaoHibernateImplTest.testGetTaxaByNameAndArea.xml
77 77
  <DESCRIPTIONELEMENTBASE DTYPE="TextData" ID="36" INDESCRIPTION_ID="2" CREATED="2008-12-10 09:56:07.0" UUID="c1e21ed1-4925-4e85-845f-e4b7a8386a33" UPDATED="2008-12-10 09:56:07.253" AREA_ID="[null]" STATUS_ID="[null]" FEATURE_ID="936" NAME="[null]"/>
78 78
  <DESCRIPTIONELEMENTBASE DTYPE="Distribution" ID="37" INDESCRIPTION_ID="34" CREATED="2008-12-10 09:56:07.0" UUID="c47cd33c-0fac-4ed2-83f1-27f83fdb4657" UPDATED="2008-12-10 09:56:07.253" AREA_ID="1970" STATUS_ID="1994" FEATURE_ID="936" NAME="[null]"/>
79 79
  <DESCRIPTIONELEMENTBASE DTYPE="CommonTaxonName" ID="38" INDESCRIPTION_ID="1" CREATED="2008-12-10 09:56:07.0" UUID="a837f822-30d6-4891-b917-cedd642ba919" UPDATED="2008-12-10 09:56:07.253" AREA_ID="[null]" STATUS_ID="[null]" FEATURE_ID="933" NAME="common name"/>
80
 <DESCRIPTIONELEMENTBASE DTYPE="CommonTaxonName" ID="39" INDESCRIPTION_ID="1" CREATED="2008-12-10 09:56:07.0" UUID="d675d475-d70a-417f-8268-e8e90991e1db" UPDATED="2008-12-10 09:56:07.253" AREA_ID="[null]" STATUS_ID="[null]" FEATURE_ID="933" NAME="commone"/>
80 81

  
81 82
  <DESCRIPTIONELEMENTBASE_LANGUAGESTRING TEXTDATA_ID="34" MULTILANGUAGETEXT_ID="1" MULTILANGUAGETEXT_MAPKEY_ID="406"/>
82 83
  <DESCRIPTIONELEMENTBASE_LANGUAGESTRING TEXTDATA_ID="35" MULTILANGUAGETEXT_ID="2" MULTILANGUAGETEXT_MAPKEY_ID="406"/>
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java
26 26
import org.apache.log4j.Logger;
27 27
import org.apache.lucene.index.CorruptIndexException;
28 28
import org.apache.lucene.queryparser.classic.ParseException;
29
import org.apache.lucene.sandbox.queries.DuplicateFilter;
29 30
import org.apache.lucene.search.BooleanClause.Occur;
30 31
import org.apache.lucene.search.BooleanQuery;
31 32
import org.apache.lucene.search.BooleanQuery.Builder;
......
641 642
        List<UuidAndTitleCache<IdentifiableEntity>> results = new ArrayList<UuidAndTitleCache<IdentifiableEntity>>();
642 643

  
643 644

  
644
        if (configurator.isDoSynonyms() || configurator.isDoTaxa() || configurator.isDoNamesWithoutTaxa()){
645
        	results = dao.getTaxaByNameForEditor(configurator.isDoTaxa(), configurator.isDoSynonyms(), configurator.isDoNamesWithoutTaxa(), configurator.isDoMisappliedNames(),configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
646
        }
647
        if (configurator.isDoTaxaByCommonNames()) {
648
            //if(configurator.getPageSize() == null ){
649
                List<UuidAndTitleCache<IdentifiableEntity>> commonNameResults = dao.getTaxaByCommonNameForEditor(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
650
                if(commonNameResults != null){
651
                    results.addAll(commonNameResults);
652
                }
653
           // }
645
        if (configurator.isDoSynonyms() || configurator.isDoTaxa() || configurator.isDoNamesWithoutTaxa() || configurator.isDoTaxaByCommonNames()){
646
        	results = dao.getTaxaByNameForEditor(configurator.isDoTaxa(), configurator.isDoSynonyms(), configurator.isDoNamesWithoutTaxa(), configurator.isDoMisappliedNames(), configurator.isDoTaxaByCommonNames(), configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
654 647
        }
648
//        if (configurator.isDoTaxaByCommonNames()) {
649
//            //if(configurator.getPageSize() == null ){
650
//                List<UuidAndTitleCache<IdentifiableEntity>> commonNameResults = dao.getTaxaByCommonNameForEditor(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
651
//                if(commonNameResults != null){
652
//                    results.addAll(commonNameResults);
653
//                }
654
//           // }
655
//        }
655 656
        return results;
656 657
    }
657 658

  
......
672 673
        }
673 674

  
674 675

  
675
       if (configurator.isDoMisappliedNames() || configurator.isDoSynonyms() || configurator.isDoTaxa()){
676
       if (configurator.isDoMisappliedNames() || configurator.isDoSynonyms() || configurator.isDoTaxa() || configurator.isDoTaxaByCommonNames()){
676 677
            if(configurator.getPageSize() != null){ // no point counting if we need all anyway
677 678
                numberTaxaResults =
678 679
                    dao.countTaxaByName(configurator.isDoTaxa(),configurator.isDoSynonyms(), configurator.isDoMisappliedNames(),
679
                        configurator.isDoIncludeAuthors(), configurator.getTitleSearchStringSqlized(),
680
                        configurator.isDoTaxaByCommonNames(), configurator.isDoIncludeAuthors(), configurator.getTitleSearchStringSqlized(),
680 681
                        configurator.getClassification(), configurator.getMatchMode(),
681 682
                        configurator.getNamedAreas());
682 683
            }
683 684

  
684 685
            if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){ // no point checking again if less results
685 686
                taxa = dao.getTaxaByName(configurator.isDoTaxa(), configurator.isDoSynonyms(),
686
                    configurator.isDoMisappliedNames(), configurator.isDoIncludeAuthors(),
687
                    configurator.isDoMisappliedNames(), configurator.isDoTaxaByCommonNames(), configurator.isDoIncludeAuthors(),
687 688
                    configurator.getTitleSearchStringSqlized(), configurator.getClassification(),
688 689
                    configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getOrder(),
689 690
                    configurator.getPageSize(), configurator.getPageNumber(), propertyPath);
......
720 721

  
721 722
        // Taxa from common names
722 723

  
723
        if (configurator.isDoTaxaByCommonNames()) {
724
            taxa = new ArrayList<>();
725
            numberTaxaResults = 0;
726
            if(configurator.getPageSize() != null){// no point counting if we need all anyway
727
                numberTaxaResults = dao.countTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
728
            }
729
            if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){
730
                List<Taxon> commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());
731
                taxa.addAll(commonNameResults);
732
            }
733
            if(taxa != null){
734
                results.addAll(taxa);
735
            }
736
            numberOfResults += numberTaxaResults;
737

  
738
        }
724
//        if (configurator.isDoTaxaByCommonNames()) {
725
//            taxa = new ArrayList<>();
726
//            numberTaxaResults = 0;
727
//            if(configurator.getPageSize() != null){// no point counting if we need all anyway
728
//                numberTaxaResults = dao.countTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());
729
//            }
730
//            if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){
731
//                List<Taxon> commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());
732
//                taxa.addAll(commonNameResults);
733
//            }
734
//            if(taxa != null){
735
//                results.addAll(taxa);
736
//            }
737
//            numberOfResults += numberTaxaResults;
738
//
739
//        }
739 740

  
740 741
       return new DefaultPagerImpl<>
741 742
            (configurator.getPageNumber(), numberOfResults, configurator.getPageSize(), results);
......
1763 1764
            byCommonNameSearch.setCdmTypRestriction(Taxon.class);
1764 1765
            byCommonNameSearch.setQuery(byCommonNameJoinQuery);
1765 1766
            byCommonNameSearch.setSortFields(sortFields);
1767

  
1768
            DuplicateFilter df = new DuplicateFilter("inDescription.taxon.id");
1769
            HashSet<String> results=new HashSet();
1770
//            ScoreDoc[] hits = searcher.search(tq,df, 1000).scoreDocs;
1771
//
1772
//            byCommonNameSearch.setFilter(df);
1766 1773
            idFieldMap.put(CdmBaseType.TAXON, "id");
1767 1774

  
1768 1775
            luceneSearches.add(byCommonNameSearch);
......
3063 3070

  
3064 3071
    @Override
3065 3072
    public List<TaxonBase> findTaxaByName(MatchingTaxonConfigurator config){
3066
        List<TaxonBase> taxonList = dao.getTaxaByName(true, false, false, false, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, null, 0, 0, config.getPropertyPath());
3073
        List<TaxonBase> taxonList = dao.getTaxaByName(true, false, false, false, false, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, null, 0, 0, config.getPropertyPath());
3067 3074
        return taxonList;
3068 3075
    }
3069 3076

  
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.java
1243 1243
        Assert.assertEquals("Expecting 1 entity", 1, pager.getCount().intValue());
1244 1244

  
1245 1245
        //FIXME FAILS: abies balamea is returned twice, see also testFullText_Grouping()
1246
        pager = taxonService.findByEverythingFullText("Balsam-Tanne", null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
1246
        pager = taxonService.findByEverythingFullText("Balsam", null, Arrays.asList(new Language[]{Language.GERMAN()}), false, null, null, null, null);
1247 1247
        logSearchResults(pager, Level.DEBUG, null);
1248 1248
        Assert.assertEquals("expecting to find the Abies balsamea via the GERMAN DescriptionElements", 1, pager.getCount().intValue());
1249 1249

  
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.xml
29 29
  <DESCRIPTIONELEMENTBASE DTYPE="TextData" ID="5002" CREATED="2013-09-23 16:10:04.0" UUID="45dadcf2-ed50-40d9-b3ff-0c34819d2ef5" UPDATED="2013-09-23 16:10:04.569" ORDERRELEVANT="[null]" NAME="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="937" INDESCRIPTION_ID="5000" AREA_ID="[null]" LANGUAGE_ID="[null]" STATUS_ID="[null]" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>
30 30
  <DESCRIPTIONELEMENTBASE DTYPE="Distribution" ID="5003" CREATED="2013-09-23 16:10:04.0" UUID="331f9689-0157-4291-bc2b-e287f3c3653e" UPDATED="2013-09-23 16:10:04.584" ORDERRELEVANT="[null]" NAME="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="923" INDESCRIPTION_ID="5000" AREA_ID="705" LANGUAGE_ID="[null]" STATUS_ID="1994" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>
31 31
  <DESCRIPTIONELEMENTBASE DTYPE="CommonTaxonName" ID="5004" CREATED="2013-09-23 16:10:04.0" UUID="c5d56f14-4826-4165-b638-4cf8c3d4deb2" UPDATED="2013-09-23 16:10:04.584" ORDERRELEVANT="[null]" NAME="Balsam-Tanne" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="933" INDESCRIPTION_ID="5000" AREA_ID="[null]" LANGUAGE_ID="349" STATUS_ID="[null]" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>
32
 <!-- <DESCRIPTIONELEMENTBASE DTYPE="CommonTaxonName" ID="5010" CREATED="2013-09-23 16:10:04.0" UUID="eb853c83-3e79-4742-8804-11b223cdaa5e" UPDATED="2013-09-23 16:10:04.584" ORDERRELEVANT="[null]" NAME="Balsam" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="933" INDESCRIPTION_ID="5000" AREA_ID="[null]" LANGUAGE_ID="349" STATUS_ID="[null]" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>-->
32 33
  <DESCRIPTIONELEMENTBASE DTYPE="CommonTaxonName" ID="5005" CREATED="2013-09-23 16:10:04.0" UUID="fc8a41af-e4e7-49e6-8fae-89d215108852" UPDATED="2013-09-23 16:10:04.585" ORDERRELEVANT="[null]" NAME="&#1041;&#1072;&#1083;&#1100;&#1079;&#1072;&#1084; &#1085;&#1100;&#1099;&#1074;" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="933" INDESCRIPTION_ID="5000" AREA_ID="[null]" LANGUAGE_ID="229" STATUS_ID="[null]" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>
33 34
  <DESCRIPTIONELEMENTBASE DTYPE="Distribution" ID="5006" CREATED="2013-09-23 16:10:04.0" UUID="130db0d0-4d4d-410c-87af-7b904dfa43b6" UPDATED="2013-09-23 16:10:04.589" ORDERRELEVANT="[null]" NAME="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="923" INDESCRIPTION_ID="5001" AREA_ID="664" LANGUAGE_ID="[null]" STATUS_ID="1993" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>
34 35
  <DESCRIPTIONELEMENTBASE DTYPE="Distribution" ID="5007" CREATED="2013-09-23 16:10:04.0" UUID="b01a427a-01c9-4f04-82a5-ca886b7ae6a8" UPDATED="2013-09-23 16:10:04.6" ORDERRELEVANT="[null]" NAME="[null]" CREATEDBY_ID="[null]" UPDATEDBY_ID="[null]" FEATURE_ID="923" INDESCRIPTION_ID="5001" AREA_ID="566" LANGUAGE_ID="[null]" STATUS_ID="1995" ASSOCIATEDSPECIMENOROBSERVATION_ID="[null]" UNIT_ID="[null]" TAXON2_ID="[null]" FORMAT_ID="[null]"/>

Also available in: Unified diff