2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.taxon
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Collection
;
13 import java
.util
.Collections
;
14 import java
.util
.Comparator
;
15 import java
.util
.HashSet
;
16 import java
.util
.Iterator
;
17 import java
.util
.List
;
19 import java
.util
.SortedSet
;
20 import java
.util
.TreeSet
;
21 import java
.util
.UUID
;
23 import org
.apache
.commons
.lang
.StringUtils
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.hibernate
.Criteria
;
26 import org
.hibernate
.FetchMode
;
27 import org
.hibernate
.Hibernate
;
28 import org
.hibernate
.Query
;
29 import org
.hibernate
.Session
;
30 import org
.hibernate
.criterion
.Criterion
;
31 import org
.hibernate
.criterion
.Order
;
32 import org
.hibernate
.criterion
.Projections
;
33 import org
.hibernate
.criterion
.Restrictions
;
34 import org
.hibernate
.envers
.query
.AuditEntity
;
35 import org
.hibernate
.envers
.query
.AuditQuery
;
36 import org
.hibernate
.envers
.query
.criteria
.internal
.NotNullAuditExpression
;
37 import org
.hibernate
.envers
.query
.internal
.property
.EntityPropertyName
;
38 import org
.hibernate
.search
.FullTextSession
;
39 import org
.hibernate
.search
.Search
;
40 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
41 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
42 import org
.springframework
.dao
.DataAccessException
;
43 import org
.springframework
.stereotype
.Repository
;
45 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
46 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
47 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
48 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
49 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
50 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
51 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
52 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
53 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
54 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameComparator
;
55 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
57 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
58 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymType
;
59 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
62 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
63 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
64 import eu
.etaxonomy
.cdm
.model
.taxon
.UuidAndTitleCacheTaxonComparator
;
65 import eu
.etaxonomy
.cdm
.model
.view
.AuditEvent
;
66 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.IdentifiableDaoBase
;
67 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
68 import eu
.etaxonomy
.cdm
.persistence
.dao
.taxon
.ITaxonDao
;
69 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonGraphEdgeDTO
;
70 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
71 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
72 import eu
.etaxonomy
.cdm
.persistence
.query
.NameSearchOrder
;
73 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
74 import eu
.etaxonomy
.cdm
.persistence
.query
.TaxonTitleType
;
82 @Qualifier("taxonDaoHibernateImpl")
83 public class TaxonDaoHibernateImpl
84 extends IdentifiableDaoBase
<TaxonBase
>
85 implements ITaxonDao
{
86 // private AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser;
87 private static final Logger logger
= Logger
.getLogger(TaxonDaoHibernateImpl
.class);
89 public TaxonDaoHibernateImpl() {
90 super(TaxonBase
.class);
91 indexedClasses
= new Class
[2];
92 indexedClasses
[0] = Taxon
.class;
93 indexedClasses
[1] = Synonym
.class;
94 super.defaultField
= "name.titleCache_tokenized";
98 private ITaxonNameDao taxonNameDao
;
100 //// spelling support currently disabled in appcontext, see spelling.xml ... "
101 //// @Autowired(required = false) //TODO switched of because it caused problems when starting CdmApplicationController
102 // public void setAlternativeSpellingSuggestionParser(AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser) {
103 // this.alternativeSpellingSuggestionParser = alternativeSpellingSuggestionParser;
107 public TaxonBase
load(UUID uuid
, List
<String
> propertyPaths
){
108 return load(uuid
, INCLUDE_UNPUBLISHED
, propertyPaths
);
112 public TaxonBase
load(UUID uuid
, boolean includeUnpublished
, List
<String
> propertyPaths
){
113 TaxonBase
<?
> result
= super.load(uuid
, includeUnpublished
, propertyPaths
);
114 return result
; //(result == null || (!result.isPublish() && !includeUnpublished))? null : result;
119 public List
<TaxonBase
> getTaxaByName(String queryString
, boolean includeUnpublished
, Reference sec
) {
121 return getTaxaByName(queryString
, true, includeUnpublished
, sec
);
125 public List
<TaxonBase
> getTaxaByName(String queryString
, Boolean accepted
, boolean includeUnpublished
, Reference sec
) {
126 checkNotInPriorView("TaxonDaoHibernateImpl.getTaxaByName(String name, Reference sec)");
128 Criteria criteria
= null;
129 if (accepted
== true) {
130 criteria
= getSession().createCriteria(Taxon
.class);
132 criteria
= getSession().createCriteria(Synonym
.class);
135 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
136 criteria
.createAlias("name", "name");
138 if (!includeUnpublished
){
139 criteria
.add(Restrictions
.eq("publish", Boolean
.TRUE
));
142 if (sec
!= null && sec
.getId() != 0) {
143 criteria
.add(Restrictions
.eq("sec", sec
) );
146 if (queryString
!= null) {
147 criteria
.add(Restrictions
.ilike("name.nameCache", queryString
));
150 @SuppressWarnings({ "unchecked", "rawtypes" })
151 List
<TaxonBase
> result
= criteria
.list();
155 //TODO needed? Currently only used by tests.
156 public List
<TaxonBase
> getTaxaByName(boolean doTaxa
, boolean doSynonyms
, boolean includeUnpublished
,
157 String queryString
, MatchMode matchMode
, Integer pageSize
, Integer pageNumber
) {
158 return getTaxaByName(doTaxa
, doSynonyms
, false, false, false,
159 queryString
, null, null, matchMode
, null, includeUnpublished
, null, pageSize
, pageNumber
, null);
163 public List
<TaxonBase
> getTaxaByName(String queryString
, MatchMode matchMode
,
164 Boolean accepted
, boolean includeUnpublished
, Integer pageSize
, Integer pageNumber
) {
166 boolean doTaxa
= true;
167 boolean doSynonyms
= true;
169 if (accepted
== true) {
174 return getTaxaByName(doTaxa
, doSynonyms
, includeUnpublished
, queryString
, matchMode
, pageSize
, pageNumber
);
178 public List
<TaxonBase
> getTaxaByName(boolean doTaxa
, boolean doSynonyms
, boolean doMisappliedNames
, boolean doCommonNames
,
179 boolean includeAuthors
,
180 String queryString
, Classification classification
, TaxonNode subtree
,
181 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, boolean includeUnpublished
, NameSearchOrder order
,
182 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
184 boolean doCount
= false;
186 String searchField
= includeAuthors ?
"titleCache" : "nameCache";
187 Query query
= prepareTaxaByName(doTaxa
, doSynonyms
, doMisappliedNames
, doCommonNames
, includeUnpublished
, searchField
, queryString
, classification
, subtree
, matchMode
, namedAreas
, order
, pageSize
, pageNumber
, doCount
);
190 @SuppressWarnings({ "unchecked", "rawtypes" })
191 List
<TaxonBase
> results
= query
.list();
193 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
195 //Collections.sort(results, comp);
198 return new ArrayList
<>();
202 //new search for the editor, for performance issues the return values are only uuid and titleCache, to avoid the initialisation of all objects
204 @SuppressWarnings("unchecked")
205 public List
<UuidAndTitleCache
<?
extends IdentifiableEntity
>> getTaxaByNameForEditor(boolean doTaxa
, boolean doSynonyms
, boolean doNamesWithoutTaxa
,
206 boolean doMisappliedNames
, boolean doCommonNames
, boolean includeUnpublished
, String queryString
, Classification classification
, TaxonNode subtree
,
207 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, NameSearchOrder order
) {
210 order
= NameSearchOrder
.ALPHA
; //TODO add to signature
213 boolean doCount
= false;
214 boolean includeAuthors
= false;
215 @SuppressWarnings("rawtypes")
216 List
<UuidAndTitleCache
<?
extends IdentifiableEntity
>> resultObjects
= new ArrayList
<>();
217 if (doNamesWithoutTaxa
){
218 List
<TaxonName
> nameResult
= taxonNameDao
.findByName(
219 includeAuthors
, queryString
, matchMode
, null, null, null, null);
221 for (TaxonName name
: nameResult
){
222 if (name
.getTaxonBases().size() == 0){
223 resultObjects
.add(new UuidAndTitleCache
<>(TaxonName
.class, name
.getUuid(),
224 name
.getId(), name
.getTitleCache()));
227 if (!doSynonyms
&& !doTaxa
&& !doCommonNames
){
228 return resultObjects
;
231 Query query
= prepareTaxaByNameForEditor(doTaxa
, doSynonyms
, doMisappliedNames
, doCommonNames
, includeUnpublished
,
232 "nameCache", queryString
, classification
, subtree
, matchMode
, namedAreas
, doCount
, order
);
235 List
<Object
[]> results
= query
.list();
238 for(int i
= 0; i
<results
.size();i
++){
239 result
= results
.get(i
);
241 //differentiate taxa and synonyms
242 // new Boolean(result[3].toString()) is due to the fact that result[3] could be a Boolean ora String
243 // see FIXME in 'prepareQuery' for more details
244 if (doTaxa
|| doSynonyms
|| doCommonNames
){
245 if (result
[3].equals("synonym")) {
246 resultObjects
.add( new UuidAndTitleCache
<>(Synonym
.class, (UUID
) result
[0], (Integer
) result
[1], (String
)result
[2], new Boolean(result
[4].toString()), null));
249 resultObjects
.add( new UuidAndTitleCache
<>(Taxon
.class, (UUID
) result
[0], (Integer
) result
[1], (String
)result
[2], new Boolean(result
[4].toString()), null));
252 }else if (doSynonyms
){
253 resultObjects
.add( new UuidAndTitleCache
<>(Synonym
.class, (UUID
) result
[0], (Integer
) result
[1], (String
)result
[2], new Boolean(result
[4].toString()), null));
257 return resultObjects
;
262 public List
<Taxon
> getTaxaByCommonName(String queryString
, Classification classification
,
263 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, Integer pageSize
,
264 Integer pageNumber
, List
<String
> propertyPaths
) {
265 boolean doCount
= false;
266 Query query
= prepareTaxaByCommonName(queryString
, classification
, matchMode
, namedAreas
, pageSize
, pageNumber
, doCount
, false);
268 @SuppressWarnings("unchecked")
269 List
<Taxon
> results
= query
.list();
270 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
273 return new ArrayList
<>();
280 * @param searchField the field in TaxonName to be searched through usually either <code>nameCache</code> or <code>titleCache</code>
282 * @param classification TODO
292 private Query
prepareTaxaByNameForEditor(boolean doTaxa
, boolean doSynonyms
, boolean doMisappliedNames
, boolean doCommonNames
,
293 boolean includeUnpublished
, String searchField
, String queryString
, Classification classification
, TaxonNode subtree
,
294 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, boolean doCount
, NameSearchOrder order
) {
295 return prepareByNameQuery(doTaxa
, doSynonyms
, doMisappliedNames
, doCommonNames
, includeUnpublished
,
296 searchField
, queryString
,
297 classification
, subtree
, matchMode
, namedAreas
, order
, doCount
, true);
304 * @param doIncludeMisappliedNames
305 * @param doCommonNames
306 * @param includeUnpublished
309 * @param classification
314 * @param returnIdAndTitle
315 * If set true the seach method will not return synonym and taxon
316 * entities but an array containing the uuid, titleCache, and the
317 * DTYPE in lowercase letters.
320 private Query
prepareByNameQuery(boolean doTaxa
, boolean doSynonyms
, boolean doMisappliedNames
,
321 boolean doCommonNames
, boolean includeUnpublished
, String searchField
, String queryString
,
322 Classification classification
, TaxonNode subtree
, MatchMode matchMode
, Set
<NamedArea
> namedAreas
,
323 NameSearchOrder order
, boolean doCount
, boolean returnIdAndTitle
){
325 boolean doProParteSynonyms
= doSynonyms
; //we may distinguish in future
326 boolean doConceptRelations
= doMisappliedNames
|| doProParteSynonyms
;
329 order
= NameSearchOrder
.DEFAULT();
331 String hqlQueryString
= matchMode
.queryStringFrom(queryString
);
333 if (returnIdAndTitle
){
334 selectWhat
= "t.uuid, t.id, t.titleCache ";
336 selectWhat
= (doCount ?
"count(t)": "t");
340 //TODO share code with taxon node filter
342 Set
<NamedArea
> areasExpanded
= new HashSet
<>();
343 if(namedAreas
!= null && namedAreas
.size() > 0){
344 // expand areas and restrict by distribution area
345 Query areaQuery
= getSession().createQuery("SELECT childArea "
346 + " FROM NamedArea AS childArea LEFT JOIN childArea.partOf as parentArea "
347 + " WHERE parentArea = :area");
348 expandNamedAreas(namedAreas
, areasExpanded
, areaQuery
);
350 boolean doAreaRestriction
= areasExpanded
.size() > 0;
352 Set
<UUID
> namedAreasUuids
= new HashSet
<>();
353 for (NamedArea area
:areasExpanded
){
354 namedAreasUuids
.add(area
.getUuid());
357 Subselects subSelects
= createByNameHQLString(doConceptRelations
,
358 includeUnpublished
, classification
, subtree
, areasExpanded
, matchMode
, searchField
);
359 String taxonSubselect
= subSelects
.taxonSubselect
;
360 String synonymSubselect
= subSelects
.synonymSubselect
;
361 String conceptSelect
= subSelects
.conceptSelect
;
362 String commonNameSubSelect
= subSelects
.commonNameSubselect
;
365 if (logger
.isDebugEnabled()) {
366 logger
.debug("taxonSubselect: " + (taxonSubselect
!= null ? taxonSubselect
: "NULL"));
367 logger
.debug("synonymSubselect: " + (synonymSubselect
!= null ? synonymSubselect
: "NULL"));
370 List
<Integer
> taxonIDs
= new ArrayList
<>();
371 List
<Integer
> synonymIDs
= new ArrayList
<>();
375 Query subTaxon
= getSearchQueryString(hqlQueryString
, taxonSubselect
);
377 addRestrictions(doAreaRestriction
, classification
, subtree
, includeUnpublished
,
378 namedAreasUuids
, subTaxon
);
379 taxonIDs
= subTaxon
.list();
384 Query subSynonym
= getSearchQueryString(hqlQueryString
, synonymSubselect
);
385 addRestrictions(doAreaRestriction
, classification
, subtree
, includeUnpublished
, namedAreasUuids
,subSynonym
);
386 synonymIDs
= subSynonym
.list();
388 if (doConceptRelations
){
389 Query subMisappliedNames
= getSearchQueryString(hqlQueryString
, conceptSelect
);
390 Set
<TaxonRelationshipType
> relTypeSet
= new HashSet
<>();
391 if (doMisappliedNames
){
392 relTypeSet
.addAll(TaxonRelationshipType
.allMisappliedNameTypes());
394 if (doProParteSynonyms
){
395 relTypeSet
.addAll(TaxonRelationshipType
.allSynonymTypes());
397 subMisappliedNames
.setParameterList("rTypeSet", relTypeSet
);
398 addRestrictions(doAreaRestriction
, classification
, subtree
, includeUnpublished
, namedAreasUuids
, subMisappliedNames
);
399 taxonIDs
.addAll(subMisappliedNames
.list());
404 Query subCommonNames
= getSearchQueryString(hqlQueryString
, commonNameSubSelect
);
405 addRestrictions(doAreaRestriction
, classification
, subtree
, includeUnpublished
, namedAreasUuids
, subCommonNames
);
406 taxonIDs
.addAll(subCommonNames
.list());
410 if(synonymIDs
.size()>0 && taxonIDs
.size()>0){
411 hql
= "SELECT " + selectWhat
;
412 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
413 // also return the computed isOrphaned flag
414 if (returnIdAndTitle
&& !doCount
){
415 hql
+= ", CASE WHEN t.id in (:taxa) THEN 'taxon' ELSE 'synonym' END, " +
416 " CASE WHEN t.id in (:taxa) "
417 + " AND t.taxonNodes IS EMPTY "
418 + " AND t.relationsFromThisTaxon IS EMPTY "
419 + " AND t.relationsToThisTaxon IS EMPTY "
420 + " THEN true ELSE false END ";
422 hql
+= " FROM %s t " +
423 " WHERE (t.id in (:taxa) OR t.id IN (:synonyms)) ";
424 }else if (synonymIDs
.size()>0 ){
425 hql
= "SELECT " + selectWhat
;
426 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
427 // also return the computed isOrphaned flag
428 if (returnIdAndTitle
&& !doCount
){
429 hql
+= ", 'synonym', 'false' ";
432 hql
+= " FROM %s t " +
433 " WHERE t.id in (:synonyms) ";
435 } else if (taxonIDs
.size()>0 ){
436 hql
= "SELECT " + selectWhat
;
437 // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:
438 // also return the computed isOrphaned flag
439 if (returnIdAndTitle
&& !doCount
){
440 hql
+= ", 'taxon', " +
441 " CASE WHEN t.taxonNodes is empty "
442 + " AND t.relationsFromThisTaxon is empty "
443 + " AND t.relationsToThisTaxon is empty "
444 + "THEN true ELSE false END ";
446 hql
+= " FROM %s t " +
447 " WHERE t.id in (:taxa) ";
448 } else if (StringUtils
.isBlank(queryString
)){
449 hql
= "SELECT " + selectWhat
+ " FROM %s t";
455 if ((doTaxa
|| doCommonNames
|| doConceptRelations
) && doSynonyms
){
456 classString
= "TaxonBase";
457 } else if (doTaxa
|| doCommonNames
){
458 classString
= "Taxon";
459 } else if (doSynonyms
&& !(doCommonNames
|| doTaxa
|| doConceptRelations
)){
460 classString
= "Synonym"; // as long as doProParteSynonyms = doSynonyms this case should not happen
461 } else{//only misappliedNames
462 classString
= "Taxon";
465 hql
= String
.format(hql
, classString
);
471 String orderBy
= " ORDER BY ";
472 String alphabeticBase
= " t.name.genusOrUninomial, case when t.name.specificEpithet like '\"%\"' then 1 else 0 end, t.name.specificEpithet, t.name.rank desc, t.name.nameCache";
474 if (order
== NameSearchOrder
.LENGTH_ALPHA_NAME
){
475 orderBy
+= " length(t.name.nameCache), " + alphabeticBase
;
476 }else if (order
== NameSearchOrder
.LENGTH_ALPHA_TITLE
){
477 orderBy
+= " length(t.name.titleCache), " + alphabeticBase
;
479 orderBy
+= alphabeticBase
;
485 if(logger
.isDebugEnabled()){ logger
.debug("hql: " + hql
);}
486 Query query
= getSession().createQuery(hql
);
488 // find taxa and synonyms
489 if (taxonIDs
.size()>0){
490 query
.setParameterList("taxa", taxonIDs
);
492 if (synonymIDs
.size()>0){
493 query
.setParameterList("synonyms",synonymIDs
);
495 if (taxonIDs
.size()== 0 && synonymIDs
.size() == 0){
503 * @param hqlQueryString
504 * @param synonymSubselect
507 protected Query
getSearchQueryString(String hqlQueryString
, String synonymSubselect
) {
508 return getSession().createQuery(synonymSubselect
).setParameter("queryString", hqlQueryString
);
512 * @param includeUnpublished
513 * @param classification
514 * @param doAreaRestriction
516 * @param namedAreasUuids
519 protected void addRestrictions(boolean doAreaRestriction
, Classification classification
, TaxonNode subtree
, boolean includeUnpublished
,
520 Set
<UUID
> namedAreasUuids
, Query query
) {
521 if(doAreaRestriction
){
522 query
.setParameterList("namedAreasUuids", namedAreasUuids
);
524 if(classification
!= null){
525 query
.setParameter("classification", classification
);
528 query
.setParameter("treeIndexLike", subtree
.treeIndex() + "%");
530 if(!includeUnpublished
){
531 query
.setBoolean("publish", true);
537 * @param searchField the field in TaxonName to be searched through usually either <code>nameCache</code> or <code>titleCache</code>
539 * @param classification TODO
548 * FIXME implement classification restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}
550 private Query
prepareTaxaByName(boolean doTaxa
, boolean doSynonyms
, boolean doMisappliedNames
,
551 boolean doCommonNames
, boolean includeUnpublished
, String searchField
, String queryString
,
552 Classification classification
, TaxonNode subtree
, MatchMode matchMode
, Set
<NamedArea
> namedAreas
, NameSearchOrder order
, Integer pageSize
, Integer pageNumber
, boolean doCount
) {
554 Query query
= prepareByNameQuery(doTaxa
, doSynonyms
, doMisappliedNames
, doCommonNames
, includeUnpublished
,
555 searchField
, queryString
, classification
, subtree
, matchMode
, namedAreas
, order
, doCount
, false);
557 if(pageSize
!= null && !doCount
&& query
!= null) {
558 query
.setMaxResults(pageSize
);
559 if(pageNumber
!= null) {
560 query
.setFirstResult(pageNumber
* pageSize
);
567 private Query
prepareTaxaByCommonName(String queryString
, Classification classification
,
568 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, Integer pageSize
, Integer pageNumber
,
569 boolean doCount
, boolean returnIdAndTitle
){
571 String what
= "select distinct";
572 if (returnIdAndTitle
){
573 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 ";
575 what
+= (doCount ?
" count(t)": " t");
577 String hql
= what
+ " from Taxon t " +
578 "join t.descriptions d "+
579 "join d.descriptionElements e " +
580 "join e.feature f " +
581 "where f.supportsCommonTaxonName = true and e.name "+matchMode
.getMatchOperator()+" :queryString";//and ls.text like 'common%'";
583 Query query
= getSession().createQuery(hql
);
585 query
.setParameter("queryString", matchMode
.queryStringFrom(queryString
));
587 if(pageSize
!= null && !doCount
) {
588 query
.setMaxResults(pageSize
);
589 if(pageNumber
!= null) {
590 query
.setFirstResult(pageNumber
* pageSize
);
597 public long countTaxaByName(boolean doTaxa
, boolean doSynonyms
, boolean doMisappliedNames
, boolean doCommonNames
,
598 boolean doIncludeAuthors
, String queryString
, Classification classification
, TaxonNode subtree
,
599 MatchMode matchMode
, Set
<NamedArea
> namedAreas
, boolean includeUnpublished
) {
601 boolean doCount
= true;
603 boolean doTaxa = true;
604 boolean doSynonyms = true;
605 if (clazz.equals(Taxon.class)){
607 } else if (clazz.equals(Synonym.class)){
611 String searchField
= doIncludeAuthors ?
"titleCache": "nameCache";
613 Query query
= prepareTaxaByName(doTaxa
, doSynonyms
, doMisappliedNames
, doCommonNames
, includeUnpublished
,
614 searchField
, queryString
, classification
, subtree
, matchMode
, namedAreas
, null, null, null, doCount
);
616 return (Long
)query
.uniqueResult();
624 * @param areasExpanded
627 private void expandNamedAreas(Collection
<NamedArea
> namedAreas
, Set
<NamedArea
> areasExpanded
, Query areaQuery
) {
628 for(NamedArea a
: namedAreas
){
629 areasExpanded
.add(a
);
630 areaQuery
.setParameter("area", a
);
631 @SuppressWarnings("unchecked")
632 List
<NamedArea
> childAreas
= areaQuery
.list();
633 if(childAreas
.size() > 0){
634 areasExpanded
.addAll(childAreas
);
635 expandNamedAreas(childAreas
, areasExpanded
, areaQuery
);
642 public UUID
delete(TaxonBase taxonBase
) throws DataAccessException
{
643 if (taxonBase
== null){
644 logger
.warn("TaxonBase was 'null'");
648 // Merge the object in if it is detached
650 // I think this is preferable to catching lazy initialization errors
651 // as that solution only swallows and hides the exception, but doesn't
652 // actually solve it.
653 taxonBase
= (TaxonBase
)getSession().merge(taxonBase
);
655 taxonBase
.removeSources();
658 if (taxonBase
instanceof Taxon
){ // is Taxon
659 Taxon taxon
= ((Taxon
)taxonBase
);
660 Set
<Synonym
> syns
= new HashSet
<>(taxon
.getSynonyms());
661 for (Synonym syn
: syns
){
662 taxon
.removeSynonym(syn
);
666 return super.delete(taxonBase
);
671 public List
<TaxonBase
> findByNameTitleCache(boolean doTaxa
, boolean doSynonyms
, boolean includeUnpublished
, String queryString
, Classification classification
, TaxonNode subtree
, MatchMode matchMode
, Set
<NamedArea
> namedAreas
, NameSearchOrder order
, Integer pageNumber
, Integer pageSize
, List
<String
> propertyPaths
) {
673 boolean doCount
= false;
674 Query query
= prepareTaxaByName(doTaxa
, doSynonyms
, false, false, includeUnpublished
, "titleCache", queryString
, classification
, subtree
, matchMode
, namedAreas
, order
, pageSize
, pageNumber
, doCount
);
676 @SuppressWarnings({ "unchecked", "rawtypes" })
677 List
<TaxonBase
> results
= query
.list();
678 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
681 return new ArrayList
<>();
686 public TaxonBase
findByUuid(UUID uuid
, List
<Criterion
> criteria
, List
<String
> propertyPaths
) {
688 Criteria crit
= getSession().createCriteria(type
);
691 crit
.add(Restrictions
.eq("uuid", uuid
));
693 logger
.warn("UUID is NULL");
696 if(criteria
!= null){
697 for (Criterion criterion
: criteria
) {
701 crit
.addOrder(Order
.asc("uuid"));
703 @SuppressWarnings({ "unchecked", "rawtypes" })
704 List
<?
extends TaxonBase
> results
= crit
.list();
705 if (results
.size() == 1) {
706 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
707 TaxonBase
<?
> taxon
= results
.iterator().next();
709 } else if (results
.size() > 1) {
710 logger
.error("Multiple results for UUID: " + uuid
);
711 } else if (results
.size() == 0) {
712 logger
.info("No results for UUID: " + uuid
);
719 public List
<?
extends TaxonBase
> findByUuids(List
<UUID
> uuids
, List
<Criterion
> criteria
, List
<String
> propertyPaths
) {
721 Criteria crit
= getSession().createCriteria(type
);
724 crit
.add(Restrictions
.in("uuid", uuids
));
726 logger
.warn("List<UUID> uuids is NULL");
729 if(criteria
!= null){
730 for (Criterion criterion
: criteria
) {
734 crit
.addOrder(Order
.asc("uuid"));
736 @SuppressWarnings({ "unchecked", "rawtypes" })
737 List
<?
extends TaxonBase
> results
= crit
.list();
739 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
744 public long countMatchesByName(String queryString
, MatchMode matchMode
, boolean onlyAcccepted
) {
745 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted)");
747 Criteria crit
= getCriteria(type
);
748 crit
.add(Restrictions
.ilike("titleCache", matchMode
.queryStringFrom(queryString
)));
749 crit
.setProjection(Projections
.rowCount());
750 return (Long
)crit
.uniqueResult();
755 public long countMatchesByName(String queryString
, MatchMode matchMode
, boolean onlyAcccepted
, List
<Criterion
> criteria
) {
756 checkNotInPriorView("TaxonDaoHibernateImpl.countMatchesByName(String queryString, ITitledDao.MATCH_MODE matchMode, boolean onlyAcccepted, List<Criterion> criteria)");
758 Criteria crit
= getCriteria(type
);
759 crit
.add(Restrictions
.ilike("titleCache", matchMode
.queryStringFrom(queryString
)));
760 if(criteria
!= null){
761 for (Criterion criterion
: criteria
) {
765 crit
.setProjection(Projections
.rowCount());
766 return (Long
)crit
.uniqueResult();
771 public long countSynonyms(boolean onlyAttachedToTaxon
) {
772 AuditEvent auditEvent
= getAuditEventFromContext();
773 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
777 " SELECT count(syn) "
778 + " FROM Synonym syn";
779 if (onlyAttachedToTaxon
){
780 queryStr
+= " WHERE syn.acceptedTaxon IS NOT NULL";
782 query
= getSession().createQuery(queryStr
);
784 return (Long
)query
.uniqueResult();
786 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(Synonym
.class,auditEvent
.getRevisionNumber());
787 if (onlyAttachedToTaxon
){
788 query
.add(new NotNullAuditExpression(new EntityPropertyName("acceptedTaxon")));
790 query
.addProjection(AuditEntity
.id().count());
792 return (Long
)query
.getSingleResult();
797 public long countSynonyms(Taxon taxon
, SynonymType type
) {
798 AuditEvent auditEvent
= getAuditEventFromContext();
799 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
800 Criteria criteria
= getCriteria(Synonym
.class);
802 criteria
.add(Restrictions
.eq("acceptedTaxon", taxon
));
804 criteria
.add(Restrictions
.eq("type", type
));
806 criteria
.setProjection(Projections
.rowCount());
807 return (Long
)criteria
.uniqueResult();
809 AuditQuery query
= makeAuditQuery(Synonym
.class,auditEvent
);
810 query
.add(AuditEntity
.relatedId("acceptedTaxon").eq(taxon
.getId()));
811 query
.addProjection(AuditEntity
.id().count());
814 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
817 return (Long
)query
.getSingleResult();
822 public long countSynonyms(Synonym synonym
, SynonymType type
) {
823 AuditEvent auditEvent
= getAuditEventFromContext();
824 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
825 Criteria criteria
= getCriteria(Synonym
.class);
827 criteria
.add(Restrictions
.isNotNull("acceptedTaxon"));
829 criteria
.add(Restrictions
.eq("type", type
));
832 criteria
.setProjection(Projections
.rowCount());
833 return (Long
)criteria
.uniqueResult();
835 AuditQuery query
= makeAuditQuery(Synonym
.class,auditEvent
);
836 query
.add(new NotNullAuditExpression(new EntityPropertyName("acceptedTaxon")));
837 query
.addProjection(AuditEntity
.id().count());
840 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
843 return (Long
)query
.getSingleResult();
848 public long countTaxaByName(Class
<?
extends TaxonBase
> clazz
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, Rank rank
) {
849 checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, Rank rank)");
850 Criteria criteria
= null;
852 criteria
= getCriteria(clazz
);
854 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
855 criteria
.createAlias("name", "name");
857 if(genusOrUninomial
== null) {
858 criteria
.add(Restrictions
.isNull("name.genusOrUninomial"));
859 } else if(!genusOrUninomial
.equals("*")) {
860 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
863 if(infraGenericEpithet
== null) {
864 criteria
.add(Restrictions
.isNull("name.infraGenericEpithet"));
865 } else if(!infraGenericEpithet
.equals("*")) {
866 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
869 if(specificEpithet
== null) {
870 criteria
.add(Restrictions
.isNull("name.specificEpithet"));
871 } else if(!specificEpithet
.equals("*")) {
872 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
876 if(infraSpecificEpithet
== null) {
877 criteria
.add(Restrictions
.isNull("name.infraSpecificEpithet"));
878 } else if(!infraSpecificEpithet
.equals("*")) {
879 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
883 criteria
.add(Restrictions
.eq("name.rank", rank
));
886 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
888 return (Long
)criteria
.uniqueResult();
892 public List
<TaxonBase
> findTaxaByName(Class
<?
extends TaxonBase
> clazz
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, String authorship
, Rank rank
, Integer pageSize
, Integer pageNumber
) {
893 checkNotInPriorView("TaxonDaoHibernateImpl.findTaxaByName(Boolean accepted, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, String authorship, Rank rank, Integer pageSize, Integer pageNumber)");
894 Criteria criteria
= getCriteria(clazz
);
896 criteria
.setFetchMode( "name", FetchMode
.JOIN
);
897 criteria
.createAlias("name", "name");
899 if(genusOrUninomial
== null) {
900 criteria
.add(Restrictions
.isNull("name.genusOrUninomial"));
901 } else if(!genusOrUninomial
.equals("*")) {
902 criteria
.add(Restrictions
.eq("name.genusOrUninomial", genusOrUninomial
));
905 if(infraGenericEpithet
== null) {
906 criteria
.add(Restrictions
.isNull("name.infraGenericEpithet"));
907 } else if(!infraGenericEpithet
.equals("*")) {
908 criteria
.add(Restrictions
.eq("name.infraGenericEpithet", infraGenericEpithet
));
911 if(specificEpithet
== null) {
912 criteria
.add(Restrictions
.isNull("name.specificEpithet"));
913 } else if(!specificEpithet
.equals("*")) {
914 criteria
.add(Restrictions
.eq("name.specificEpithet", specificEpithet
));
917 if(infraSpecificEpithet
== null) {
918 criteria
.add(Restrictions
.isNull("name.infraSpecificEpithet"));
919 } else if(!infraSpecificEpithet
.equals("*")) {
920 criteria
.add(Restrictions
.eq("name.infraSpecificEpithet", infraSpecificEpithet
));
923 if(authorship
== null) {
924 criteria
.add(Restrictions
.eq("name.authorshipCache", ""));
925 } else if(!authorship
.equals("*")) {
926 criteria
.add(Restrictions
.eq("name.authorshipCache", authorship
));
930 criteria
.add(Restrictions
.eq("name.rank", rank
));
933 if(pageSize
!= null) {
934 criteria
.setMaxResults(pageSize
);
935 if(pageNumber
!= null) {
936 criteria
.setFirstResult(pageNumber
* pageSize
);
938 criteria
.setFirstResult(0);
942 @SuppressWarnings({ "unchecked", "rawtypes" })
943 List
<TaxonBase
> result
= criteria
.list();
948 public long countTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
,
949 boolean includeUnpublished
, Direction direction
) {
950 Set
<TaxonRelationshipType
> types
= null;
952 types
= new HashSet
<>();
955 return countTaxonRelationships(taxon
, types
, includeUnpublished
, direction
);
959 public long countTaxonRelationships(Taxon taxon
, Set
<TaxonRelationshipType
> types
,
960 boolean includeUnpublished
, Direction direction
) {
961 AuditEvent auditEvent
= getAuditEventFromContext();
962 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
964 String queryString
= prepareTaxonRelationshipQuery(types
, includeUnpublished
, direction
, true);
965 Query query
= getSession().createQuery(queryString
);
966 query
.setParameter("relatedTaxon", taxon
);
968 query
.setParameterList("types",types
);
970 if(! includeUnpublished
) {
971 query
.setBoolean("publish",Boolean
.TRUE
);
975 // if(type == null) {
976 // query = getSession().createQuery(
977 // "select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon");
979 // query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon and taxonRelationship.type = :type");
980 // query.setParameter("type",type);
982 // query.setParameter("relatedTaxon", taxon);
984 return (Long
)query
.uniqueResult();
988 AuditQuery query
= makeAuditQuery(TaxonRelationship
.class, auditEvent
);
989 query
.add(AuditEntity
.relatedId(direction
.toString()).eq(taxon
.getId()));
990 query
.addProjection(AuditEntity
.id().count());
993 //TODO adapt to new Set semantic, was single type before
994 // query.add(AuditEntity.relatedId("type").eq(type.getId()));
997 return (Long
)query
.getSingleResult();
1004 * @param includeUnpublished
1009 private String
prepareTaxonRelationshipQuery(Set
<TaxonRelationshipType
> types
, boolean includeUnpublished
,
1010 Direction direction
, boolean isCount
) {
1011 String selectStr
= isCount?
" count(rel) as n ":" rel ";
1012 String result
= "SELECT " + selectStr
+ " FROM TaxonRelationship rel ";
1013 if(direction
!= null){
1014 result
+= " WHERE rel."+direction
+" = :relatedTaxon";
1016 result
+= " WHERE (rel.relatedFrom = :relatedTaxon OR rel.relatedTo = :relatedTaxon )";
1019 result
+= " AND rel.type IN (:types) ";
1021 if(! includeUnpublished
) {
1022 result
+= " AND rel."+direction
.invers()+".publish = :publish";
1028 public List
<TaxonRelationship
> getTaxonRelationships(Taxon taxon
, TaxonRelationshipType type
,
1029 boolean includeUnpublished
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
1030 List
<String
> propertyPaths
, Direction direction
) {
1031 Set
<TaxonRelationshipType
> types
= null;
1033 types
= new HashSet
<>();
1036 return getTaxonRelationships(taxon
, types
, includeUnpublished
, pageSize
, pageNumber
, orderHints
, propertyPaths
, direction
);
1040 public List
<TaxonRelationship
> getTaxonRelationships(Taxon taxon
, Set
<TaxonRelationshipType
> types
,
1041 boolean includeUnpublished
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
,
1042 List
<String
> propertyPaths
, Direction direction
) {
1044 AuditEvent auditEvent
= getAuditEventFromContext();
1045 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
1047 String queryString
= prepareTaxonRelationshipQuery(types
, includeUnpublished
, direction
, false);
1049 queryString
+= orderByClause("rel", orderHints
);
1051 Query query
= getSession().createQuery(queryString
);
1052 query
.setParameter("relatedTaxon", taxon
);
1054 query
.setParameterList("types",types
);
1056 if(! includeUnpublished
) {
1057 query
.setBoolean("publish",Boolean
.TRUE
);
1059 setPagingParameter(query
, pageSize
, pageNumber
);
1061 // Criteria criteria = getSession().createCriteria(TaxonRelationship.class);
1063 // if(direction != null) {
1064 // criteria.add(Restrictions.eq(direction.name(), taxon));
1066 // criteria.add(Restrictions.or(
1067 // Restrictions.eq(Direction.relatedFrom.name(), taxon),
1068 // Restrictions.eq(Direction.relatedTo.name(), taxon))
1072 // if(type != null) {
1073 // criteria.add(Restrictions.eq("type", type));
1076 // addOrder(criteria,orderHints);
1078 // if(pageSize != null) {
1079 // criteria.setMaxResults(pageSize);
1080 // if(pageNumber != null) {
1081 // criteria.setFirstResult(pageNumber * pageSize);
1083 // criteria.setFirstResult(0);
1087 @SuppressWarnings("unchecked")
1088 List
<TaxonRelationship
> result
= query
.list();
1089 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1094 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship
.class,auditEvent
.getRevisionNumber());
1095 query
.add(AuditEntity
.relatedId("relatedTo").eq(taxon
.getId()));
1098 //FIXME adapt to Set (was single type before)
1099 // query.add(AuditEntity.relatedId("type").eq(types.getId()));
1102 if(pageSize
!= null) {
1103 query
.setMaxResults(pageSize
);
1104 if(pageNumber
!= null) {
1105 query
.setFirstResult(pageNumber
* pageSize
);
1107 query
.setFirstResult(0);
1111 @SuppressWarnings("unchecked")
1112 List
<TaxonRelationship
> result
= query
.getResultList();
1113 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1115 // Ugly, but for now, there is no way to sort on a related entity property in Envers,
1116 // and we can't live without this functionality in CATE as it screws up the whole
1118 if(orderHints
!= null && !orderHints
.isEmpty()) {
1119 SortedSet
<TaxonRelationship
> sortedList
= new TreeSet
<>(new TaxonRelationshipFromTaxonComparator());
1120 sortedList
.addAll(result
);
1121 return new ArrayList
<>(sortedList
);
1128 class TaxonRelationshipFromTaxonComparator
implements Comparator
<TaxonRelationship
> {
1131 public int compare(TaxonRelationship o1
, TaxonRelationship o2
) {
1135 int result
= o1
.getFromTaxon().getTitleCache().compareTo(o2
.getFromTaxon().getTitleCache());
1137 result
= o1
.getUuid().compareTo(o2
.getUuid());
1145 public List
<Synonym
> getSynonyms(Taxon taxon
, SynonymType type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1146 AuditEvent auditEvent
= getAuditEventFromContext();
1147 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
1148 Criteria criteria
= getSession().createCriteria(Synonym
.class);
1150 criteria
.add(Restrictions
.eq("acceptedTaxon", taxon
));
1152 criteria
.add(Restrictions
.eq("type", type
));
1155 addOrder(criteria
,orderHints
);
1157 if(pageSize
!= null) {
1158 criteria
.setMaxResults(pageSize
);
1159 if(pageNumber
!= null) {
1160 criteria
.setFirstResult(pageNumber
* pageSize
);
1162 criteria
.setFirstResult(0);
1166 @SuppressWarnings("unchecked")
1167 List
<Synonym
> result
= criteria
.list();
1168 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1172 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(Synonym
.class,auditEvent
.getRevisionNumber());
1173 query
.add(AuditEntity
.relatedId("acceptedTaxon").eq(taxon
.getId()));
1176 query
.add(AuditEntity
.relatedId("type").eq(type
.getId()));
1179 if(pageSize
!= null) {
1180 query
.setMaxResults(pageSize
);
1181 if(pageNumber
!= null) {
1182 query
.setFirstResult(pageNumber
* pageSize
);
1184 query
.setFirstResult(0);
1188 @SuppressWarnings("unchecked")
1189 List
<Synonym
> result
= query
.getResultList();
1190 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1197 public void rebuildIndex() {
1198 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
1200 for(TaxonBase
<?
> taxonBase
: list(null,null)) { // re-index all taxon base
1201 Hibernate
.initialize(taxonBase
.getName());
1202 fullTextSession
.index(taxonBase
);
1204 fullTextSession
.flushToIndexes();
1208 public String
suggestQuery(String queryString
) {
1209 throw new RuntimeException("Query suggestion currently not implemented in TaxonDaoHibernateImpl");
1210 // checkNotInPriorView("TaxonDaoHibernateImpl.suggestQuery(String queryString)");
1211 // String alternativeQueryString = null;
1212 // if (alternativeSpellingSuggestionParser != null) {
1215 // alternativeSpellingSuggestionParser.parse(queryString);
1216 // org.apache.lucene.search.Query alternativeQuery = alternativeSpellingSuggestionParser.suggest(queryString);
1217 // if (alternativeQuery != null) {
1218 // alternativeQueryString = alternativeQuery
1219 // .toString("name.titleCache");
1222 // } catch (ParseException e) {
1223 // throw new QueryParseException(e, queryString);
1226 // return alternativeQueryString;
1230 public Taxon
acceptedTaxonFor(Synonym synonym
, Classification classificationFilter
, List
<String
> propertyPaths
){
1232 String hql
= prepareListAcceptedTaxaFor(classificationFilter
, false);
1234 Query query
= getSession().createQuery(hql
);
1235 query
.setParameter("synonym", synonym
);
1236 if(classificationFilter
!= null){
1237 query
.setParameter("classificationFilter", classificationFilter
);
1240 @SuppressWarnings("unchecked")
1241 List
<Taxon
> result
= query
.list();
1243 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1245 return result
.isEmpty()?
null: result
.get(0);
1249 public long countAcceptedTaxonFor(Synonym synonym
, Classification classificationFilter
){
1251 String hql
= prepareListAcceptedTaxaFor(classificationFilter
, true);
1253 Query query
= getSession().createQuery(hql
);
1254 query
.setParameter("synonym", synonym
);
1255 if(classificationFilter
!= null){
1256 query
.setParameter("classificationFilter", classificationFilter
);
1259 Long count
= Long
.parseLong(query
.uniqueResult().toString());
1266 * @param classificationFilter
1270 private String
prepareListAcceptedTaxaFor(Classification classificationFilter
, boolean doCount
) {
1273 String hqlSelect
= "SELECT " + (doCount?
"COUNT(taxon)" : "taxon") +
1274 " FROM Synonym as syn "
1275 + " JOIN syn.acceptedTaxon as taxon ";
1276 String hqlWhere
= " WHERE syn = :synonym";
1278 if(classificationFilter
!= null){
1279 hqlSelect
+= " JOIN taxon.taxonNodes AS taxonNode";
1280 hqlWhere
+= " AND taxonNode.classification = :classificationFilter";
1282 hql
= hqlSelect
+ hqlWhere
;
1287 public TaxonBase
find(LSID lsid
) {
1288 TaxonBase
<?
> taxonBase
= super.find(lsid
);
1289 if(taxonBase
!= null) {
1290 List
<String
> propertyPaths
= new ArrayList
<>();
1291 propertyPaths
.add("createdBy");
1292 propertyPaths
.add("updatedBy");
1293 propertyPaths
.add("name");
1294 propertyPaths
.add("sec");
1295 propertyPaths
.add("relationsToThisTaxon");
1296 propertyPaths
.add("relationsToThisTaxon.fromTaxon");
1297 propertyPaths
.add("relationsToThisTaxon.toTaxon");
1298 propertyPaths
.add("relationsFromThisTaxon");
1299 propertyPaths
.add("relationsFromThisTaxon.toTaxon");
1300 propertyPaths
.add("relationsToThisTaxon.type");
1301 propertyPaths
.add("synonyms");
1302 propertyPaths
.add("synonyms.type");
1303 propertyPaths
.add("descriptions");
1305 defaultBeanInitializer
.initialize(taxonBase
, propertyPaths
);
1311 public List
<String
> taxaByNameNotInDB(List
<String
> taxonNames
){
1312 //get all taxa, already in db
1313 Query query
= getSession().createQuery(
1314 " FROM TaxonName t "
1315 +" WHERE t.nameCache IN (:taxonList)");
1316 query
.setParameterList("taxonList", taxonNames
);
1317 @SuppressWarnings("unchecked")
1318 List
<TaxonName
> taxaInDB
= query
.list();
1319 //compare the original list with the result of the query
1320 for (TaxonName taxonName
: taxaInDB
){
1321 String nameCache
= taxonName
.getNameCache();
1322 if (taxonNames
.contains(nameCache
)){
1323 taxonNames
.remove(nameCache
);
1330 //TODO: mal nur mit UUID probieren (ohne fetch all properties), vielleicht geht das schneller?
1332 public List
<UUID
> findIdenticalTaxonNameIds(List
<String
> propertyPaths
){
1333 Query query
=getSession().createQuery(
1335 + " FROM ZoologicalName tmb, ZoologicalName tmb2 FETCH ALL properties "
1336 + " WHERE tmb.id != tmb2.id AND tmb.nameCache = tmb2.nameCache");
1337 @SuppressWarnings("unchecked")
1338 List
<UUID
> zooNames
= query
.list();
1345 public List
<TaxonName
> findIdenticalTaxonNames(List
<String
> propertyPaths
) {
1347 Query query
=getSession().createQuery(
1349 + " FROM ZoologicalName tmb, ZoologicalName tmb2 FETCH ALL properties "
1350 + " WHERE tmb.id != tmb2.id AND tmb.nameCache = tmb2.nameCache");
1352 @SuppressWarnings("unchecked")
1353 List
<TaxonName
> zooNames
= query
.list();
1355 TaxonNameComparator taxComp
= new TaxonNameComparator();
1356 Collections
.sort(zooNames
, taxComp
);
1358 for (TaxonName taxonName
: zooNames
){
1359 defaultBeanInitializer
.initialize(taxonName
, propertyPaths
);
1366 public List
<TaxonName
> findIdenticalNamesNew(List
<String
> propertyPaths
){
1368 //Hole die beiden Source_ids von "Fauna Europaea" und "Erms" und in sources der names darf jeweils nur das entgegengesetzte auftreten (i member of tmb.taxonBases)
1369 Query query
= getSession().createQuery("SELECT id "
1371 + " WHERE titleCache LIKE 'Fauna Europaea database'");
1372 @SuppressWarnings("unchecked")
1373 List
<String
> secRefFauna
= query
.list();
1374 query
= getSession().createQuery("Select id from Reference where titleCache like 'ERMS'");
1375 @SuppressWarnings("unchecked")
1376 List
<String
> secRefErms
= query
.list();
1377 //Query query = getSession().createQuery("select tmb2.nameCache from ZoologicalName tmb, TaxonBase tb1, ZoologicalName tmb2, TaxonBase tb2 where tmb.id != tmb2.id and tb1.name = tmb and tb2.name = tmb2 and tmb.nameCache = tmb2.nameCache and tb1.sec != tb2.sec");
1378 //Get all names of fauna europaea
1379 query
= getSession().createQuery("select zn.nameCache from ZoologicalName zn, TaxonBase tb where tb.name = zn and tb.sec.id = :secRefFauna");
1380 query
.setParameter("secRefFauna", secRefFauna
.get(0));
1381 @SuppressWarnings("unchecked")
1382 List
<String
> namesFauna
= query
.list();
1384 //Get all names of erms
1386 query
= getSession().createQuery("select zn.nameCache from ZoologicalName zn, TaxonBase tb where tb.name = zn and tb.sec.id = :secRefErms");
1387 query
.setParameter("secRefErms", secRefErms
.get(0));
1389 @SuppressWarnings("unchecked")
1390 List
<String
> namesErms
= query
.list();
1391 /*TaxonNameComparator comp = new TaxonNameComparator();
1392 Collections.sort(namesFauna);
1393 Collections.sort(namesErms);
1395 List
<String
> identicalNames
= new ArrayList
<>();
1397 for (String nameFauna
: namesFauna
){
1398 if (namesErms
.contains(nameFauna
)){
1399 identicalNames
.add(nameFauna
);
1403 query
= getSession().createQuery("from ZoologicalName zn where zn.nameCache IN (:identicalNames)");
1404 query
.setParameterList("identicalNames", identicalNames
);
1405 List
<TaxonName
> result
= query
.list();
1406 TaxonName tempName
= result
.get(0);
1408 Iterator
<IdentifiableSource
> sources
= tempName
.getSources().iterator();
1410 TaxonNameComparator taxComp
= new TaxonNameComparator();
1411 Collections
.sort(result
, taxComp
);
1412 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
1420 // public String getPhylumName(TaxonName name){
1421 // List results = new ArrayList();
1423 // Query query = getSession().createSQLQuery("select getPhylum("+ name.getId()+");");
1424 // results = query.list();
1425 // }catch(Exception e){
1426 // System.err.println(name.getUuid());
1429 // System.err.println("phylum of "+ name.getTitleCache() );
1430 // return (String)results.get(0);
1435 public long countTaxaByCommonName(String searchString
,
1436 Classification classification
, MatchMode matchMode
,
1437 Set
<NamedArea
> namedAreas
) {
1438 boolean doCount
= true;
1439 Query query
= prepareTaxaByCommonName(searchString
, classification
, matchMode
, namedAreas
, null, null, doCount
, false);
1440 if (query
!= null && !query
.list().isEmpty()) {
1441 Object o
= query
.uniqueResult();
1449 private Subselects
createByNameHQLString(boolean doConceptRelations
,
1450 boolean includeUnpublished
, Classification classification
, TaxonNode subtree
,
1451 Set
<NamedArea
> areasExpanded
, MatchMode matchMode
, String searchField
){
1454 boolean doAreaRestriction
= areasExpanded
.size() > 0;
1455 boolean hasTaxonNodeFilter
= classification
!= null || subtree
!= null;
1457 String doAreaRestrictionSubSelect
=
1459 + " FROM Distribution e "
1460 + " JOIN e.inDescription d "
1461 + " JOIN d.taxon t " +
1462 (hasTaxonNodeFilter ?
" JOIN t.taxonNodes AS tn " : " ");
1464 String doAreaRestrictionConceptRelationSubSelect
=
1466 + " FROM Distribution e "
1467 + " JOIN e.inDescription d"
1468 + " JOIN d.taxon t";
1470 String doTaxonSubSelect
=
1472 + " FROM Taxon t " + (hasTaxonNodeFilter ?
" "
1473 + " JOIN t.taxonNodes AS tn " : " ");
1475 String doTaxonMisappliedNameSubSelect
=
1479 String doTaxonNameJoin
= " JOIN t.name n ";
1481 String doSynonymNameJoin
=
1482 " JOIN t.synonyms s "
1483 + " JOIN s.name sn";
1485 String doConceptRelationJoin
=
1486 " LEFT JOIN t.relationsFromThisTaxon AS rft " +
1487 " LEFT JOIN rft.relatedTo AS rt " +
1488 (hasTaxonNodeFilter ?
" LEFT JOIN rt.taxonNodes AS tn2 " : " ") +
1489 " LEFT JOIN rt.name AS n2" +
1490 " LEFT JOIN rft.type as rtype";
1492 String doCommonNamesJoin
=
1493 " JOIN t.descriptions AS description "+
1494 " LEFT JOIN description.descriptionElements AS com " +
1495 " LEFT JOIN com.feature f ";
1498 String doTreeWhere
= classification
== null ?
"" : " AND tn.classification = :classification";
1499 String doTreeForConceptRelationsWhere
= classification
== null ?
"": " AND tn2.classification = :classification";
1501 String doSubtreeWhere
= subtree
== null?
"":" AND tn.treeIndex like :treeIndexLike";
1502 String doSubtreeForConceptRelationsWhere
= subtree
== null?
"":" AND tn2.treeIndex like :treeIndexLike";
1504 String doAreaRestrictionWhere
= " e.area.uuid in (:namedAreasUuids)";
1505 String doCommonNamesRestrictionWhere
= " (f.supportsCommonTaxonName = true and com.name "+matchMode
.getMatchOperator()+" :queryString )";
1507 String doSearchFieldWhere
= "%s." + searchField
+ " " + matchMode
.getMatchOperator() + " :queryString";
1509 String doRelationshipTypeComparison
= " rtype in (:rTypeSet) ";
1511 String taxonSubselect
= null;
1512 String synonymSubselect
= null;
1513 String conceptSelect
= null;
1514 String commonNameSubselect
= null;
1516 if(hasTaxonNodeFilter
){
1517 if (!doConceptRelations
){
1518 if(doAreaRestriction
){
1519 taxonSubselect
= String
.format(doAreaRestrictionSubSelect
, "t") + doTaxonNameJoin
+
1520 " WHERE (1=1) AND " + doAreaRestrictionWhere
+
1521 doTreeWhere
+ doSubtreeWhere
+
1522 " AND " + String
.format(doSearchFieldWhere
, "n");
1523 synonymSubselect
= String
.format(doAreaRestrictionSubSelect
, "s") + doSynonymNameJoin
+
1524 " WHERE (1=1) AND " + doAreaRestrictionWhere
+
1525 doTreeWhere
+ doSubtreeWhere
+
1526 " AND " + String
.format(doSearchFieldWhere
, "sn");
1527 commonNameSubselect
= String
.format(doAreaRestrictionSubSelect
, "t") + doCommonNamesJoin
+
1528 " WHERE (1=1) AND " + doAreaRestrictionWhere
+
1529 doTreeWhere
+ doSubtreeWhere
+
1530 " AND " + String
.format(doSearchFieldWhere
, "n") +
1531 " AND " + doCommonNamesRestrictionWhere
;
1532 } else {//no area restriction
1533 taxonSubselect
= String
.format(doTaxonSubSelect
, "t" )+ doTaxonNameJoin
+
1534 " WHERE (1=1) " + doTreeWhere
+ doSubtreeWhere
+
1535 " AND " + String
.format(doSearchFieldWhere
, "n");
1536 synonymSubselect
= String
.format(doTaxonSubSelect
, "s" ) + doSynonymNameJoin
+
1537 " WHERE (1=1) " + doTreeWhere
+ doSubtreeWhere
+
1538 " AND " + String
.format(doSearchFieldWhere
, "sn");
1539 commonNameSubselect
=String
.format(doTaxonSubSelect
, "t" )+ doCommonNamesJoin
+
1540 " WHERE (1=1) " + doTreeWhere
+ doSubtreeWhere
+
1541 " AND " + doCommonNamesRestrictionWhere
;
1543 }else{ //concept relations included
1544 if(doAreaRestriction
){
1545 conceptSelect
= String
.format(doAreaRestrictionConceptRelationSubSelect
, "t") + doTaxonNameJoin
+ doConceptRelationJoin
+
1546 " WHERE " + doAreaRestrictionWhere
+
1547 " AND " + String
.format(doSearchFieldWhere
, "n") +
1548 doTreeForConceptRelationsWhere
+ doSubtreeForConceptRelationsWhere
+
1549 " AND " + doRelationshipTypeComparison
;
1550 taxonSubselect
= String
.format(doAreaRestrictionSubSelect
, "t") + doTaxonNameJoin
+
1551 " WHERE " + doAreaRestrictionWhere
+
1552 " AND " + String
.format(doSearchFieldWhere
, "n") +
1553 doTreeWhere
+ doSubtreeWhere
;
1554 synonymSubselect
= String
.format(doAreaRestrictionSubSelect
, "s") + doSynonymNameJoin
+
1555 " WHERE " + doAreaRestrictionWhere
+
1556 doTreeWhere
+ doSubtreeWhere
+
1557 " AND " + String
.format(doSearchFieldWhere
, "sn");
1558 commonNameSubselect
= String
.format(doAreaRestrictionSubSelect
, "t")+ doCommonNamesJoin
+
1559 " WHERE " + doAreaRestrictionWhere
+
1560 doTreeWhere
+ doSubtreeWhere
+
1561 " AND " + doCommonNamesRestrictionWhere
;
1562 } else {//no area restriction
1563 conceptSelect
= String
.format(doTaxonMisappliedNameSubSelect
, "t" ) + doTaxonNameJoin
+ doConceptRelationJoin
+
1564 " WHERE " + String
.format(doSearchFieldWhere
, "n") +
1565 doTreeForConceptRelationsWhere
+ doSubtreeForConceptRelationsWhere
+
1566 " AND " + doRelationshipTypeComparison
;
1567 taxonSubselect
= String
.format(doTaxonSubSelect
, "t" ) + doTaxonNameJoin
+
1568 " WHERE " + String
.format(doSearchFieldWhere
, "n") +
1569 doTreeWhere
+ doSubtreeWhere
;
1570 synonymSubselect
= String
.format(doTaxonSubSelect
, "s" ) + doSynonymNameJoin
+
1571 " WHERE (1=1) " + doTreeWhere
+ doSubtreeWhere
+
1572 " AND " + String
.format(doSearchFieldWhere
, "sn");
1573 commonNameSubselect
= String
.format(doTaxonSubSelect
, "t")+ doCommonNamesJoin
+
1574 " WHERE (1=1) " + doTreeWhere
+ doSubtreeWhere
+
1575 " AND " + doCommonNamesRestrictionWhere
;
1578 } else { //classification = null && subtree = null
1579 if(doAreaRestriction
){
1580 conceptSelect
= String
.format(doAreaRestrictionConceptRelationSubSelect
, "t") + doTaxonNameJoin
+ doConceptRelationJoin
+
1581 " WHERE " + doAreaRestrictionWhere
+
1582 " AND " + String
.format(doSearchFieldWhere
, "n")+
1583 " AND " + doRelationshipTypeComparison
;
1584 taxonSubselect
= String
.format(doAreaRestrictionSubSelect
, "t") + doTaxonNameJoin
+
1585 " WHERE " + doAreaRestrictionWhere
+
1586 " AND " + String
.format(doSearchFieldWhere
, "n");
1587 synonymSubselect
= String
.format(doAreaRestrictionSubSelect
, "s") + doSynonymNameJoin
+
1588 " WHERE " + doAreaRestrictionWhere
+
1589 " AND " + String
.format(doSearchFieldWhere
, "sn");
1590 commonNameSubselect
= String
.format(doAreaRestrictionSubSelect
, "t")+ doCommonNamesJoin
+
1591 " WHERE " + doAreaRestrictionWhere
+
1592 " AND " + doCommonNamesRestrictionWhere
;
1593 } else { //no area restriction
1594 conceptSelect
= String
.format(doTaxonMisappliedNameSubSelect
, "t" ) + doTaxonNameJoin
+ doConceptRelationJoin
+
1595 " WHERE " + String
.format(doSearchFieldWhere
, "n") +
1596 " AND " + doRelationshipTypeComparison
;
1597 taxonSubselect
= String
.format(doTaxonSubSelect
, "t" ) + doTaxonNameJoin
+
1598 " WHERE " + String
.format(doSearchFieldWhere
, "n");
1599 synonymSubselect
= String
.format(doTaxonSubSelect
, "s" ) + doSynonymNameJoin
+
1600 " WHERE " + String
.format(doSearchFieldWhere
, "sn");
1601 commonNameSubselect
= String
.format(doTaxonSubSelect
, "t" ) +doCommonNamesJoin
+
1602 " WHERE "+ doCommonNamesRestrictionWhere
;
1606 if (!includeUnpublished
){
1607 taxonSubselect
+= " AND t.publish = :publish ";
1608 synonymSubselect
+= " AND s.publish = :publish AND t.publish = :publish ";
1609 commonNameSubselect
+= " AND t.publish = :publish ";
1610 conceptSelect
+= " AND t.publish = :publish AND rt.publish = :publish ";
1613 Subselects result
= new Subselects(taxonSubselect
, synonymSubselect
, conceptSelect
, commonNameSubselect
);
1617 private class Subselects
{
1618 String taxonSubselect
;
1619 String synonymSubselect
;
1620 String conceptSelect
;
1621 String commonNameSubselect
;
1622 private Subselects(String taxonSubselect
, String synonymSubselect
, String conceptSelect
,
1623 String commonNameSubselect
) {
1624 this.taxonSubselect
= taxonSubselect
;
1625 this.synonymSubselect
= synonymSubselect
;
1626 this.conceptSelect
= conceptSelect
;
1627 this.commonNameSubselect
= commonNameSubselect
;
1632 public List
<UuidAndTitleCache
<Taxon
>> getTaxaByCommonNameForEditor(
1633 String titleSearchStringSqlized
, Classification classification
,
1634 MatchMode matchMode
, Set
<NamedArea
> namedAreas
) {
1635 Query query
= prepareTaxaByCommonName(titleSearchStringSqlized
, classification
, matchMode
, namedAreas
, null, null, false, true);
1637 @SuppressWarnings("unchecked")
1638 List
<Object
> resultArray
= query
.list();
1639 List
<UuidAndTitleCache
<Taxon
>> returnResult
= new ArrayList
<>() ;
1641 for(int i
= 0; i
<resultArray
.size();i
++){
1642 result
= (Object
[]) resultArray
.get(i
);
1643 returnResult
.add(new UuidAndTitleCache
<Taxon
>(Taxon
.class, (UUID
) result
[0],(Integer
)result
[1], (String
)result
[2], new Boolean(result
[4].toString()), null));
1645 return returnResult
;
1647 return new ArrayList
<>();
1654 * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countByIdentifier(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.common.DefinedTerm, eu.etaxonomy.cdm.model.taxon.TaxonNode, eu.etaxonomy.cdm.persistence.query.MatchMode)
1657 public <S
extends TaxonBase
> long countByIdentifier(Class
<S
> clazz
,
1658 String identifier
, DefinedTerm identifierType
, TaxonNode subtreeFilter
, MatchMode matchmode
) {
1659 if (subtreeFilter
== null){
1660 return countByIdentifier(clazz
, identifier
, identifierType
, matchmode
);
1663 Class
<?
> clazzParam
= (clazz
== null) ? type
: clazz
;
1664 checkNotInPriorView("TaxonDaoHibernateImpl.countByIdentifier(T clazz, String identifier, DefinedTerm identifierType, TaxonNode subMatchMode matchmode)");
1666 boolean isTaxon
= clazzParam
== Taxon
.class || clazzParam
== TaxonBase
.class;
1667 boolean isSynonym
= clazzParam
== Synonym
.class || clazzParam
== TaxonBase
.class;
1669 getSession().update(subtreeFilter
); //to avoid LIE when retrieving treeindex
1670 String filterStr
= "'" + subtreeFilter
.treeIndex() + "%%'";
1671 String accTreeJoin
= isTaxon?
" LEFT JOIN c.taxonNodes tn " : "";
1672 String synTreeJoin
= isSynonym ?
" LEFT JOIN c.acceptedTaxon as acc LEFT JOIN acc.taxonNodes synTn " : "";
1673 String accWhere
= isTaxon ?
"tn.treeIndex like " + filterStr
: "(1=0)";
1674 String synWhere
= isSynonym ?
"synTn.treeIndex like " + filterStr
: "(1=0)";
1676 String queryString
= "SELECT count(*) FROM %s as c " +
1677 " INNER JOIN c.identifiers as ids " +
1681 " AND ( " + accWhere
+ " OR " + synWhere
+ ")";
1682 queryString
= String
.format(queryString
, clazzParam
.getSimpleName());
1684 if (identifier
!= null){
1685 if (matchmode
== null || matchmode
== MatchMode
.EXACT
){
1686 queryString
+= " AND ids.identifier = '" + identifier
+ "'";
1688 queryString
+= " AND ids.identifier LIKE '" + matchmode
.queryStringFrom(identifier
) + "'";
1691 if (identifierType
!= null){
1692 queryString
+= " AND ids.type = :type";
1695 Query query
= getSession().createQuery(queryString
);
1696 if (identifierType
!= null){
1697 query
.setEntity("type", identifierType
);
1700 return (Long
)query
.uniqueResult();
1704 public <S
extends TaxonBase
> List
<Object
[]> findByIdentifier(
1705 Class
<S
> clazz
, String identifier
, DefinedTerm identifierType
, TaxonNode subtreeFilter
,
1706 MatchMode matchmode
, boolean includeEntity
,
1707 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
1709 checkNotInPriorView("TaxonDaoHibernateImpl.findByIdentifier(T clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
1710 Class
<?
> clazzParam
= clazz
== null ? type
: clazz
;
1712 boolean isTaxon
= clazzParam
== Taxon
.class || clazzParam
== TaxonBase
.class;
1713 boolean isSynonym
= clazzParam
== Synonym
.class || clazzParam
== TaxonBase
.class;
1714 getSession().update(subtreeFilter
); //to avoid LIE when retrieving treeindex
1715 String filterStr
= "'" + subtreeFilter
.treeIndex() + "%%'";
1716 String accTreeJoin
= isTaxon?
" LEFT JOIN c.taxonNodes tn " : "";
1717 String synTreeJoin
= isSynonym ?
" LEFT JOIN c.acceptedTaxon as acc LEFT JOIN acc.taxonNodes synTn " : "";
1718 String accWhere
= isTaxon ?
"tn.treeIndex like " + filterStr
: "(1=0)";
1719 String synWhere
= isSynonym ?
"synTn.treeIndex like " + filterStr
: "(1=0)";
1721 String queryString
= " SELECT ids.type, ids.identifier, %s " +
1723 " INNER JOIN c.identifiers as ids " +
1727 " AND ( " + accWhere
+ " OR " + synWhere
+ ")";
1728 queryString
= String
.format(queryString
, (includeEntity ?
"c":"c.uuid, c.titleCache") , clazzParam
.getSimpleName());
1730 //Matchmode and identifier
1731 if (identifier
!= null){
1732 if (matchmode
== null || matchmode
== MatchMode
.EXACT
){
1733 queryString
+= " AND ids.identifier = '" + identifier
+ "'";
1735 queryString
+= " AND ids.identifier LIKE '" + matchmode
.queryStringFrom(identifier
) + "'";
1738 if (identifierType
!= null){
1739 queryString
+= " AND ids.type = :type";
1742 queryString
+=" ORDER BY ids.type.uuid, ids.identifier, c.uuid ";
1744 Query query
= getSession().createQuery(queryString
);
1747 if (identifierType
!= null){
1748 query
.setEntity("type", identifierType
);
1752 setPagingParameter(query
, pageSize
, pageNumber
);
1754 List
<Object
[]> results
= query
.list();
1757 List
<S
> entities
= new ArrayList
<S
>();
1758 for (Object
[] result
: results
){
1759 entities
.add((S
)result
[2]);
1761 defaultBeanInitializer
.initializeAll(entities
, propertyPaths
);
1768 * @see #countByIdentifier(Class, String, DefinedTerm, TaxonNode, MatchMode)
1771 public <S
extends TaxonBase
> long countByMarker(Class
<S
> clazz
, MarkerType markerType
,
1772 Boolean markerValue
, TaxonNode subtreeFilter
) {
1773 if (markerType
== null){
1777 if (subtreeFilter
== null){
1778 return countByMarker(clazz
, markerType
, markerValue
);
1781 Class
<?
> clazzParam
= clazz
== null ? type
: clazz
;
1782 checkNotInPriorView("TaxonDaoHibernateImpl.countByMarker(Class<S> clazz, DefinedTerm markerType, boolean markerValue, TaxonNode subtreeFilter)");
1784 boolean isTaxon
= clazzParam
== Taxon
.class || clazzParam
== TaxonBase
.class;
1785 boolean isSynonym
= clazzParam
== Synonym
.class || clazzParam
== TaxonBase
.class;
1787 getSession().update(subtreeFilter
); //to avoid LIE when retrieving treeindex
1788 String filterStr
= "'" + subtreeFilter
.treeIndex() + "%%'";
1789 String accTreeJoin
= isTaxon?
" LEFT JOIN c.taxonNodes tn " : "";
1790 String synTreeJoin
= isSynonym ?
" LEFT JOIN c.acceptedTaxon acc LEFT JOIN acc.taxonNodes synTn " : "";
1791 String accWhere
= isTaxon ?
"tn.treeIndex like " + filterStr
: "(1=0)";
1792 String synWhere
= isSynonym ?
"synTn.treeIndex like " + filterStr
: "(1=0)";
1794 String queryString
= "SELECT count(*) FROM %s as c " +
1795 " INNER JOIN c.markers as mks " +
1799 " AND ( " + accWhere
+ " OR " + synWhere
+ ")";
1800 queryString
= String
.format(queryString
, clazzParam
.getSimpleName());
1802 if (markerValue
!= null){
1803 queryString
+= " AND mks.flag = :flag";
1805 if (markerType
!= null){
1806 queryString
+= " AND mks.markerType = :type";
1809 Query query
= getSession().createQuery(queryString
);
1810 if (markerType
!= null){
1811 query
.setEntity("type", markerType
);
1813 if (markerValue
!= null){
1814 query
.setBoolean("flag", markerValue
);
1817 Long c
= (Long
)query
.uniqueResult();
1825 public <S
extends TaxonBase
> List
<Object
[]> findByMarker(Class
<S
> clazz
, MarkerType markerType
,
1826 Boolean markerValue
, TaxonNode subtreeFilter
, boolean includeEntity
,
1827 TaxonTitleType titleType
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
1828 checkNotInPriorView("TaxonDaoHibernateImpl.findByMarker(T clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
1829 if (markerType
== null){
1830 return new ArrayList
<Object
[]>();
1832 if (titleType
== null){
1833 titleType
= TaxonTitleType
.DEFAULT();
1836 Class
<?
> clazzParam
= clazz
== null ? type
: clazz
;
1838 boolean isTaxon
= clazzParam
== Taxon
.class || clazzParam
== TaxonBase
.class;
1839 boolean isSynonym
= clazzParam
== Synonym
.class || clazzParam
== TaxonBase
.class;
1840 getSession().update(subtreeFilter
); //to avoid LIE when retrieving treeindex
1841 String filterStr
= "'" + subtreeFilter
.treeIndex() + "%%'";
1842 String accTreeJoin
= isTaxon?
" LEFT JOIN c.taxonNodes tn " : "";
1843 String synTreeJoin
= isSynonym ?
" LEFT JOIN c.acceptedTaxon as acc LEFT JOIN acc.taxonNodes synTn " : "";
1844 String accWhere
= isTaxon ?
"tn.treeIndex like " + filterStr
: "(1=0)";
1845 String synWhere
= isSynonym ?
"synTn.treeIndex like " + filterStr
: "(1=0)";
1846 String selectParams
= includeEntity ?
"c" : titleType
.hqlReplaceSelect("c.uuid, c.titleCache", "c.titleCache");
1847 String titleTypeJoin
= includeEntity ?
"" : titleType
.hqlJoin();
1849 String queryString
= "SELECT mks.markerType, mks.flag, %s " +
1851 " INNER JOIN c.markers as mks " +
1856 " AND ( " + accWhere
+ " OR " + synWhere
+ ")";
1857 queryString
= String
.format(queryString
, selectParams
, clazzParam
.getSimpleName());
1860 if (markerValue
!= null){
1861 queryString
+= " AND mks.flag = :flag";
1863 queryString
+= " AND mks.markerType = :type";
1865 queryString
+=" ORDER BY mks.markerType.uuid, mks.flag, c.uuid ";
1867 Query query
= getSession().createQuery(queryString
);
1870 query
.setEntity("type", markerType
);
1871 if (markerValue
!= null){
1872 query
.setBoolean("flag", markerValue
);
1876 setPagingParameter(query
, pageSize
, pageNumber
);
1878 List
<Object
[]> results
= query
.list();
1881 List
<S
> entities
= new ArrayList
<S
>();
1882 for (Object
[] result
: results
){
1883 entities
.add((S
)result
[2]);
1885 defaultBeanInitializer
.initializeAll(entities
, propertyPaths
);
1891 public long countTaxonRelationships(Set
<TaxonRelationshipType
> types
) {
1892 Criteria criteria
= getSession().createCriteria(TaxonRelationship
.class);
1894 if (types
!= null) {
1895 if (types
.isEmpty()){
1898 criteria
.add(Restrictions
.in("type", types
) );
1902 criteria
.setProjection(Projections
.rowCount());
1903 long result
= (Long
)criteria
.uniqueResult();
1909 public List
<TaxonRelationship
> getTaxonRelationships(Set
<TaxonRelationshipType
> types
,
1910 Integer pageSize
, Integer pageNumber
,
1911 List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
1912 Criteria criteria
= getCriteria(TaxonRelationship
.class);
1914 if (types
!= null) {
1915 if (types
.isEmpty()){
1916 return new ArrayList
<>();
1918 criteria
.add(Restrictions
.in("type", types
) );
1921 addOrder(criteria
,orderHints
);
1922 addPageSizeAndNumber(criteria
, pageSize
, pageNumber
);
1924 @SuppressWarnings("unchecked")
1925 List
<TaxonRelationship
> results
= criteria
.list();
1926 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
1932 public List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCache(Integer limit
, String pattern
){
1933 Session session
= getSession();
1935 if (pattern
!= null){
1936 query
= session
.createQuery(
1937 " SELECT tb.uuid, tb.id, tb.titleCache, tb.name.rank "
1938 + " FROM TaxonBase as tb "
1939 + " WHERE tb.titleCache LIKE :pattern");
1940 pattern
= pattern
.replace("*", "%");
1941 pattern
= pattern
.replace("?", "_");
1942 pattern
= pattern
+ "%";
1943 query
.setParameter("pattern", pattern
);
1945 query
= session
.createQuery(
1946 " SELECT tb.uuid, taxonBase.id, tb.titleCache, tb.name.rank "
1947 + " FROM TaxonBase AS tb");
1950 query
.setMaxResults(limit
);
1953 return getUuidAndTitleCache(query
);
1957 protected List
<UuidAndTitleCache
<TaxonBase
>> getUuidAndTitleCache(Query query
){
1958 List
<UuidAndTitleCache
<TaxonBase
>> list
= new ArrayList
<>();
1960 @SuppressWarnings("unchecked")
1961 List
<Object
[]> result
= query
.list();
1962 if (!result
.isEmpty()){
1963 if (result
.iterator().next().length
== 4){
1964 Collections
.sort(result
, new UuidAndTitleCacheTaxonComparator());
1968 for(Object
[] object
: result
){
1969 list
.add(new UuidAndTitleCache
<TaxonBase
>((UUID
) object
[0],(Integer
) object
[1], (String
) object
[2]));
1978 public List
<TaxonGraphEdgeDTO
> getTaxonGraphEdgeDTOs(UUID fromTaxonUuid
, UUID toTaxonUuid
, TaxonRelationshipType type
,
1979 boolean includeUnpublished
) {
1981 Session session
= getSession();
1982 String hql
= "select new eu.etaxonomy.cdm.persistence.dto.TaxonGraphEdgeDTO(fromT.uuid, fromT.titleCache, toT.uuid, toT.titleCache, c.uuid, c.titleCache) "
1983 + "FROM TaxonRelationship as tr "
1984 + "JOIN tr.relatedTo as toT "
1985 + "JOIN tr.relatedFrom as fromT "
1986 + "JOIN tr.citation as c "
1987 + "WHERE tr.type = :reltype AND toT.uuid = :toTaxonUuid AND fromT.uuid = :fromTaxonUuid";
1989 if(!includeUnpublished
){
1990 hql
+= " AND toT.publish is true AND fromT.publish is true";
1993 Query query
= session
.createQuery(hql
);
1994 query
.setParameter("reltype", type
);
1995 query
.setParameter("fromTaxonUuid", fromTaxonUuid
);
1996 query
.setParameter("toTaxonUuid", toTaxonUuid
);
1998 List
<TaxonGraphEdgeDTO
> result
= query
.list();