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.
10 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.description
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashSet
;
14 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.apache
.commons
.lang
.ArrayUtils
;
20 import org
.apache
.logging
.log4j
.LogManager
;
21 import org
.apache
.logging
.log4j
.Logger
;
22 import org
.hibernate
.Criteria
;
23 import org
.hibernate
.criterion
.Criterion
;
24 import org
.hibernate
.criterion
.ProjectionList
;
25 import org
.hibernate
.criterion
.Projections
;
26 import org
.hibernate
.criterion
.Restrictions
;
27 import org
.hibernate
.envers
.query
.AuditEntity
;
28 import org
.hibernate
.envers
.query
.AuditQuery
;
29 import org
.hibernate
.query
.Query
;
30 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
31 import org
.springframework
.stereotype
.Repository
;
33 import eu
.etaxonomy
.cdm
.model
.common
.LSID
;
34 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
35 import eu
.etaxonomy
.cdm
.model
.description
.CommonTaxonName
;
36 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
37 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
38 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionType
;
39 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
40 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
41 import eu
.etaxonomy
.cdm
.model
.description
.PresenceAbsenceTerm
;
42 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
43 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
44 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
45 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
46 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
47 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
49 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTerm
;
50 import eu
.etaxonomy
.cdm
.model
.view
.AuditEvent
;
51 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.OperationNotSupportedInPriorViewException
;
52 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
53 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.IdentifiableDaoBase
;
54 import eu
.etaxonomy
.cdm
.persistence
.dto
.SortableTaxonNodeQueryResult
;
55 import eu
.etaxonomy
.cdm
.persistence
.dto
.TermDto
;
56 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
57 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
60 @Qualifier("descriptionDaoImpl")
61 public class DescriptionDaoImpl
62 extends IdentifiableDaoBase
<DescriptionBase
>
63 implements IDescriptionDao
{
65 private static final Logger logger
= LogManager
.getLogger(DescriptionDaoImpl
.class);
67 public DescriptionDaoImpl() {
68 super(DescriptionBase
.class);
69 indexedClasses
= new Class
[3];
70 indexedClasses
[0] = TaxonDescription
.class;
71 indexedClasses
[1] = TaxonNameDescription
.class;
72 indexedClasses
[2] = SpecimenDescription
.class;
75 // @Override //Override for testing
76 // public DescriptionBase load(UUID uuid, List<String> propertyPaths){
77 // DescriptionBase bean = findByUuid(uuid);
81 // defaultBeanInitializer.initialize(bean, propertyPaths);
87 public long countDescriptionByDistribution(Set
<NamedArea
> namedAreas
, PresenceAbsenceTerm status
) {
88 checkNotInPriorView("DescriptionDaoImpl.countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status)");
89 Query
<Long
> query
= null;
92 query
= getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.descriptionElements element join element.area area where area in (:namedAreas)", Long
.class);
94 query
= getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.descriptionElements element join element.area area join element.status status where area in (:namedAreas) and status = :status", Long
.class);
95 query
.setParameter("status", status
);
97 query
.setParameterList("namedAreas", namedAreas
);
99 return query
.uniqueResult();
103 public <T
extends DescriptionElementBase
> long countDescriptionElements(DescriptionBase description
, Set
<Feature
> features
, Class
<T
> clazz
) {
104 return countDescriptionElements(description
, null, features
, clazz
);
108 public <T
extends DescriptionElementBase
> long countDescriptionElements(DescriptionBase description
, Class
<?
extends DescriptionBase
> descriptionType
,
109 Set
<Feature
> features
, Class
<T
> clazz
) {
110 AuditEvent auditEvent
= getAuditEventFromContext();
112 clazz
= (Class
<T
>)DescriptionElementBase
.class;
114 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
115 Criteria criteria
= getCriteria(clazz
);
117 if(description
!= null) {
118 criteria
.add(Restrictions
.eq("inDescription", description
));
121 if(descriptionType
!= null) {
122 criteria
.createAlias("inDescription", "d").add(Restrictions
.eq("d.class", descriptionType
));
125 if(features
!= null && !features
.isEmpty()) {
126 criteria
.add(Restrictions
.in("feature", features
));
129 criteria
.setProjection(Projections
.rowCount());
131 return (Long
)criteria
.uniqueResult();
133 if(features
!= null && !features
.isEmpty()) {
135 for(Feature f
: features
) {
136 AuditQuery query
= null;
137 query
= makeAuditQuery(clazz
, auditEvent
);
139 if(description
!= null) {
140 query
.add(AuditEntity
.relatedId("inDescription").eq(description
.getId()));
143 if(descriptionType
!= null) {
144 query
.add(AuditEntity
.property("inDescription.class").eq(descriptionType
));
147 query
.add(AuditEntity
.relatedId("feature").eq(f
.getId()));
148 query
.addProjection(AuditEntity
.id().count());
149 count
+= (Long
)query
.getSingleResult();
154 AuditQuery query
= makeAuditQuery(clazz
, auditEvent
);
156 if(description
!= null) {
157 query
.add(AuditEntity
.relatedId("inDescription").eq(description
.getId()));
159 if(descriptionType
!= null) {
160 query
.add(AuditEntity
.property("inDescription.class").eq(descriptionType
));
163 query
.addProjection(AuditEntity
.id().count());
164 return (Long
)query
.getSingleResult();
170 public long countDescriptions(Class
<?
extends DescriptionBase
> clazz
, Boolean hasImages
, Boolean hasText
, Set
<Feature
> features
) {
171 checkNotInPriorView("DescriptionDaoImpl.countDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features)");
173 Criteria inner
= getCriteria(clazz
);
175 Criteria elementsCriteria
= inner
.createCriteria("descriptionElements");
176 if(hasText
!= null) {
178 elementsCriteria
.add(Restrictions
.isNotEmpty("multilanguageText"));
180 elementsCriteria
.add(Restrictions
.isEmpty("multilanguageText"));
184 if(hasImages
!= null) {
186 elementsCriteria
.add(Restrictions
.isNotEmpty("media"));
188 elementsCriteria
.add(Restrictions
.isEmpty("media"));
192 if(features
!= null && !features
.isEmpty()) {
193 elementsCriteria
.add(Restrictions
.in("feature", features
));
196 inner
.setProjection(Projections
.countDistinct("id"));
198 return (Long
)inner
.uniqueResult();
202 public long countTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
,
203 Set
<NamedArea
> geographicalScopes
, Set
<MarkerType
> markerTypes
, Set
<DescriptionType
> descriptionTypes
) {
204 AuditEvent auditEvent
= getAuditEventFromContext();
205 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
206 Criteria criteria
= getCriteria(TaxonDescription
.class);
209 criteria
.add(Restrictions
.eq("taxon", taxon
));
212 if(scopes
!= null && !scopes
.isEmpty()) {
213 Set
<Integer
> scopeIds
= new HashSet
<>();
214 for(DefinedTerm s
: scopes
) {
215 scopeIds
.add(s
.getId());
217 criteria
.createCriteria("scopes").add(Restrictions
.in("id", scopeIds
));
220 if(geographicalScopes
!= null && !geographicalScopes
.isEmpty()) {
221 Set
<Integer
> geoScopeIds
= new HashSet
<>();
222 for(NamedArea n
: geographicalScopes
) {
223 geoScopeIds
.add(n
.getId());
225 criteria
.createCriteria("geoScopes").add(Restrictions
.in("id", geoScopeIds
));
228 addMarkerTypesCriterion(markerTypes
, criteria
);
229 addDescriptionTypesCriterion(descriptionTypes
, criteria
);
231 criteria
.setProjection(Projections
.rowCount());
233 return (Long
)criteria
.uniqueResult();
235 if((scopes
== null || scopes
.isEmpty())&& (geographicalScopes
== null || geographicalScopes
.isEmpty()) && (markerTypes
== null || markerTypes
.isEmpty())) {
236 AuditQuery query
= makeAuditQuery(TaxonDescription
.class,auditEvent
);
238 query
.add(AuditEntity
.relatedId("taxon").eq(taxon
.getId()));
241 query
.addProjection(AuditEntity
.id().count());
243 return (Long
)query
.getSingleResult();
245 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
250 private void addDescriptionTypesCriterion(Set
<DescriptionType
> descriptionTypes
, Criteria criteria
) {
251 if(descriptionTypes
!= null && !descriptionTypes
.isEmpty()) {
252 Set
<Criterion
> typeCriteria
= new HashSet
<>();
253 for (DescriptionType descriptionType
: descriptionTypes
) {
254 typeCriteria
.add(Restrictions
.sqlRestriction("{alias}.types like '%"+descriptionType
.getKey()+"%'"));
256 criteria
.add(Restrictions
.and(typeCriteria
.toArray(new Criterion
[]{})));
265 //TODO move to AnnotatableEntityDao(?)
266 private void addMarkerTypesCriterion(Set
<MarkerType
> markerTypes
, Criteria criteria
) {
268 if(markerTypes
!= null && !markerTypes
.isEmpty()) {
269 Set
<Integer
> markerTypeIds
= new HashSet
<Integer
>();
270 for(MarkerType markerType
: markerTypes
) {
271 markerTypeIds
.add(markerType
.getId());
273 criteria
.createCriteria("markers").add(Restrictions
.eq("flag", true))
274 .createAlias("markerType", "mt")
275 .add(Restrictions
.in("mt.id", markerTypeIds
));
276 } else if (markerTypes
!= null && markerTypes
.isEmpty()){
277 //AT: added in case the projects requires an third state description, An empty Marker type set
281 public <T
extends DescriptionElementBase
> List
<T
> getDescriptionElements(
282 DescriptionBase description
, Set
<Feature
> features
,
283 Class
<T
> clazz
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
284 return getDescriptionElements(description
, null, features
, clazz
, pageSize
, pageNumber
, propertyPaths
);
288 public <T
extends DescriptionElementBase
> List
<T
> getDescriptionElements(
289 DescriptionBase description
, Class
<?
extends DescriptionBase
> descriptionType
,
290 Set
<Feature
> features
,
292 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
294 AuditEvent auditEvent
= getAuditEventFromContext();
295 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
296 Criteria criteria
= null;
298 criteria
= getSession().createCriteria(DescriptionElementBase
.class);
300 criteria
= getSession().createCriteria(clazz
);
303 if(description
!= null) {
304 criteria
.add(Restrictions
.eq("inDescription", description
));
306 if(descriptionType
!= null) {
307 criteria
.createAlias("inDescription", "d").add(Restrictions
.eq("d.class", descriptionType
));
310 if(features
!= null && !features
.isEmpty()) {
311 criteria
.add(Restrictions
.in("feature", features
));
314 if(pageSize
!= null) {
315 criteria
.setMaxResults(pageSize
);
316 if(pageNumber
!= null) {
317 criteria
.setFirstResult(pageNumber
* pageSize
);
321 List
<T
> results
= criteria
.list();
322 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
325 List
<T
> result
= new ArrayList
<T
>();
326 if(features
!= null && !features
.isEmpty()) {
328 for(Feature f
: features
) {
329 AuditQuery query
= null;
331 query
= getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase
.class,auditEvent
.getRevisionNumber());
333 query
= getAuditReader().createQuery().forEntitiesAtRevision(clazz
,auditEvent
.getRevisionNumber());
336 if(description
!= null) {
337 query
.add(AuditEntity
.relatedId("inDescription").eq(description
.getId()));
340 if(descriptionType
!= null) {
341 query
.add(AuditEntity
.property("inDescription.class").eq(descriptionType
));
344 query
.add(AuditEntity
.relatedId("feature").eq(f
.getId()));
345 result
.addAll(query
.getResultList());
348 AuditQuery query
= null;
350 query
= getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase
.class,auditEvent
.getRevisionNumber());
352 query
= getAuditReader().createQuery().forEntitiesAtRevision(clazz
,auditEvent
.getRevisionNumber());
355 if(description
!= null) {
356 query
.add(AuditEntity
.relatedId("inDescription").eq(description
.getId()));
359 if(descriptionType
!= null) {
360 query
.add(AuditEntity
.property("inDescription.class").eq(descriptionType
));
363 result
= query
.getResultList();
366 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
372 public List
<TaxonDescription
> listTaxonDescriptions(Taxon taxon
, Set
<DefinedTerm
> scopes
, Set
<NamedArea
> geographicalScopes
, Set
<MarkerType
> markerTypes
, Set
<DescriptionType
> descriptionTypes
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
373 AuditEvent auditEvent
= getAuditEventFromContext();
374 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
375 Criteria criteria
= getSession().createCriteria(TaxonDescription
.class);
378 criteria
.add(Restrictions
.eq("taxon", taxon
));
381 if(scopes
!= null && !scopes
.isEmpty()) {
382 Set
<Integer
> scopeIds
= new HashSet
<Integer
>();
383 for(DefinedTerm s
: scopes
) {
384 scopeIds
.add(s
.getId());
386 criteria
.createCriteria("scopes").add(Restrictions
.in("id", scopeIds
));
389 if(geographicalScopes
!= null && !geographicalScopes
.isEmpty()) {
390 Set
<Integer
> geoScopeIds
= new HashSet
<Integer
>();
391 for(NamedArea n
: geographicalScopes
) {
392 geoScopeIds
.add(n
.getId());
394 criteria
.createCriteria("geoScopes").add(Restrictions
.in("id", geoScopeIds
));
397 addMarkerTypesCriterion(markerTypes
, criteria
);
398 addDescriptionTypesCriterion(descriptionTypes
, criteria
);
400 if(pageSize
!= null) {
401 criteria
.setMaxResults(pageSize
);
402 if(pageNumber
!= null) {
403 criteria
.setFirstResult(pageNumber
* pageSize
);
407 List
<TaxonDescription
> results
= criteria
.list();
409 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
413 if((scopes
== null || scopes
.isEmpty())&& (geographicalScopes
== null || geographicalScopes
.isEmpty())&& (markerTypes
== null || markerTypes
.isEmpty())) {
414 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(TaxonDescription
.class,auditEvent
.getRevisionNumber());
416 query
.add(AuditEntity
.relatedId("taxon").eq(taxon
.getId()));
419 if(pageSize
!= null) {
420 query
.setMaxResults(pageSize
);
421 if(pageNumber
!= null) {
422 query
.setFirstResult(pageNumber
* pageSize
);
424 query
.setFirstResult(0);
428 List
<TaxonDescription
> results
= query
.getResultList();
429 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
432 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
438 public List
<TaxonNameDescription
> getTaxonNameDescriptions(TaxonName name
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
439 AuditEvent auditEvent
= getAuditEventFromContext();
440 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
441 Criteria criteria
= getSession().createCriteria(TaxonNameDescription
.class);
444 criteria
.add(Restrictions
.eq("taxonName", name
));
447 if(pageSize
!= null) {
448 criteria
.setMaxResults(pageSize
);
449 if(pageNumber
!= null) {
450 criteria
.setFirstResult(pageNumber
* pageSize
);
454 List
<TaxonNameDescription
> results
= criteria
.list();
456 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
460 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription
.class,auditEvent
.getRevisionNumber());
463 query
.add(AuditEntity
.relatedId("taxonName").eq(name
.getId()));
466 if(pageSize
!= null) {
467 query
.setMaxResults(pageSize
);
468 if(pageNumber
!= null) {
469 query
.setFirstResult(pageNumber
* pageSize
);
473 List
<TaxonNameDescription
> results
= query
.getResultList();
474 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
480 public long countTaxonNameDescriptions(TaxonName name
) {
481 AuditEvent auditEvent
= getAuditEventFromContext();
482 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
483 Criteria criteria
= getCriteria(TaxonNameDescription
.class);
486 criteria
.add(Restrictions
.eq("taxonName", name
));
489 criteria
.setProjection(Projections
.rowCount());
491 return (Long
)criteria
.uniqueResult();
493 AuditQuery query
= makeAuditQuery(TaxonNameDescription
.class,auditEvent
);
496 query
.add(AuditEntity
.relatedId("taxonName").eq(name
.getId()));
499 query
.addProjection(AuditEntity
.id().count());
500 return (Long
)query
.getSingleResult();
505 * Should use a DetachedCriteria & subquery, but HHH-158 prevents this, for now.
507 * e.g. DetachedCriteria inner = DestachedCriteria.forClass(type);
509 * outer.add(Subqueries.propertyIn("id", inner));
512 public List
<DescriptionBase
> listDescriptions(Class
<?
extends DescriptionBase
> clazz
, Boolean hasImages
, Boolean hasText
, Set
<Feature
> features
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
513 checkNotInPriorView("DescriptionDaoImpl.listDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features, Integer pageSize, Integer pageNumber)");
514 Criteria inner
= getCriteria(clazz
);
516 Criteria elementsCriteria
= inner
.createCriteria("descriptionElements");
517 if(hasText
!= null) {
519 elementsCriteria
.add(Restrictions
.isNotEmpty("multilanguageText"));
521 elementsCriteria
.add(Restrictions
.isEmpty("multilanguageText"));
525 if(hasImages
!= null) {
527 elementsCriteria
.add(Restrictions
.isNotEmpty("media"));
529 elementsCriteria
.add(Restrictions
.isEmpty("media"));
533 if(features
!= null && !features
.isEmpty()) {
534 elementsCriteria
.add(Restrictions
.in("feature", features
));
537 inner
.setProjection(Projections
.distinct(Projections
.id()));
539 @SuppressWarnings("unchecked")
540 List
<Object
> intermediateResult
= inner
.list();
542 if(intermediateResult
.isEmpty()) {
543 return new ArrayList
<>();
546 Integer
[] resultIds
= new Integer
[intermediateResult
.size()];
547 for(int i
= 0; i
< resultIds
.length
; i
++) {
548 resultIds
[i
] = (Integer
)intermediateResult
.get(i
);
551 Criteria outer
= getCriteria(clazz
);
553 outer
.add(Restrictions
.in("id", resultIds
));
554 addOrder(outer
, orderHints
);
556 addPageSizeAndNumber(outer
, pageSize
, pageNumber
);
558 @SuppressWarnings({ "unchecked", "rawtypes" })
559 List
<DescriptionBase
> results
= outer
.list();
560 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
565 public List
<TaxonDescription
> searchDescriptionByDistribution(Set
<NamedArea
> namedAreas
, PresenceAbsenceTerm status
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
566 checkNotInPriorView("DescriptionDaoImpl.searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
568 Criteria criteria
= getSession().createCriteria(TaxonDescription
.class);
569 Criteria elements
= criteria
.createCriteria("descriptionElements", "descriptionElement", Criteria
.LEFT_JOIN
);
570 elements
.add(Restrictions
.in("area", namedAreas
.toArray()));
573 elements
.add(Restrictions
.eq("status", status
));
576 ProjectionList projectionList
= Projections
.projectionList().add(Projections
.id());
578 if(orderHints
!= null && !orderHints
.isEmpty()) {
579 for(OrderHint orderHint
: orderHints
) {
580 projectionList
= projectionList
.add(Projections
.property(orderHint
.getPropertyName()));
584 criteria
.setProjection(Projections
.distinct(projectionList
));
586 if(pageSize
!= null) {
587 criteria
.setMaxResults(pageSize
);
588 if(pageNumber
!= null) {
589 criteria
.setFirstResult(pageNumber
* pageSize
);
593 addOrder(criteria
,orderHints
);
595 @SuppressWarnings("unchecked")
596 List
<Object
> intermediateResult
= criteria
.list();
598 if(intermediateResult
.isEmpty()) {
599 return new ArrayList
<>();
602 Integer
[] resultIds
= new Integer
[intermediateResult
.size()];
603 for(int i
= 0; i
< resultIds
.length
; i
++) {
604 if(orderHints
== null || orderHints
.isEmpty()) {
605 resultIds
[i
] = (Integer
)intermediateResult
.get(i
);
607 resultIds
[i
] = ((Number
)((Object
[])intermediateResult
.get(i
))[0]).intValue();
611 criteria
= getSession().createCriteria(TaxonDescription
.class);
612 criteria
.add(Restrictions
.in("id", resultIds
));
613 addOrder(criteria
,orderHints
);
615 @SuppressWarnings("unchecked")
616 List
<TaxonDescription
> results
= criteria
.list();
617 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
622 public List
<CommonTaxonName
> searchDescriptionByCommonName(String queryString
, MatchMode matchMode
, Integer pageSize
, Integer pageNumber
) {
624 Criteria crit
= getSession().createCriteria(CommonTaxonName
.class);
625 if (matchMode
== MatchMode
.EXACT
) {
626 crit
.add(Restrictions
.eq("name", matchMode
.queryStringFrom(queryString
)));
628 crit
.add(Restrictions
.ilike("name", matchMode
.queryStringFrom(queryString
)));
631 if(pageSize
!= null) {
632 crit
.setMaxResults(pageSize
);
633 if(pageNumber
!= null) {
634 crit
.setFirstResult(pageNumber
* pageSize
);
637 @SuppressWarnings("unchecked")
638 List
<CommonTaxonName
> results
= crit
.list();
643 public Integer
countDescriptionByCommonName(String queryString
, MatchMode matchMode
) {
644 //TODO inprove performance
645 List
<CommonTaxonName
> results
= searchDescriptionByCommonName(queryString
, matchMode
, null, null);
646 return results
.size();
650 public DescriptionBase
find(LSID lsid
) {
651 DescriptionBase
<?
> descriptionBase
= super.find(lsid
);
652 if(descriptionBase
!= null) {
653 List
<String
> propertyPaths
= new ArrayList
<>();
654 propertyPaths
.add("createdBy");
655 propertyPaths
.add("updatedBy");
656 propertyPaths
.add("taxon");
657 propertyPaths
.add("taxonName");
658 propertyPaths
.add("descriptionElements");
659 propertyPaths
.add("descriptionElements.createdBy");
660 propertyPaths
.add("descriptionElements.updatedBy");
661 propertyPaths
.add("descriptionElements.feature");
662 propertyPaths
.add("descriptionElements.multilanguageText");
663 propertyPaths
.add("descriptionElements.multilanguageText.language");
664 propertyPaths
.add("descriptionElements.area");
665 propertyPaths
.add("descriptionElements.status");
666 propertyPaths
.add("descriptionElements.modifyingText");
667 propertyPaths
.add("descriptionElementsmodifyingText.language");
668 propertyPaths
.add("descriptionElements.modifiers");
670 defaultBeanInitializer
.initialize(descriptionBase
, propertyPaths
);
672 return descriptionBase
;
677 public List
<Integer
> getIndividualAssociationSpecimenIDs(UUID taxonUuid
,
678 Set
<Feature
> features
, Integer pageSize
,
679 Integer pageNumber
, List
<String
> propertyPaths
){
680 Query
<Integer
> query
= prepareGetDescriptionElementForTaxon(taxonUuid
, features
, IndividualsAssociation
.class, pageSize
, pageNumber
, "de.associatedSpecimenOrObservation.id");
681 List
<Integer
> results
= query
.list();
686 public List
<SortableTaxonNodeQueryResult
> getNodeOfIndividualAssociationForSpecimen(UUID specimenUuid
, UUID classificationUuid
){
687 String selectString
= " new " +SortableTaxonNodeQueryResult
.class.getName()+"(n.uuid, n.id, n.treeIndex, t.uuid, t.titleCache, t.name.titleCache, t.name.rank, n.parent.uuid) ";
688 Query
<SortableTaxonNodeQueryResult
> query
= prepareGetIndividualAssociationForSpecimen(specimenUuid
, classificationUuid
, selectString
);
689 @SuppressWarnings("unchecked")
690 List
<SortableTaxonNodeQueryResult
> results
= query
.list();
695 public <T
extends DescriptionElementBase
> List
<T
> getDescriptionElementForTaxon(
696 UUID taxonUuid
, Set
<Feature
> features
,
697 Class
<T
> type
, Integer pageSize
,
698 Integer pageNumber
, List
<String
> propertyPaths
) {
700 // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
701 Query
<T
> query
= prepareGetDescriptionElementForTaxon(taxonUuid
, features
, type
, pageSize
, pageNumber
, "de");
703 if (logger
.isDebugEnabled()){logger
.debug(" dao: get list ...");}
704 List
<T
> results
= query
.list();
705 if (logger
.isDebugEnabled()){logger
.debug(" dao: initialize ...");}
706 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
707 if (logger
.isDebugEnabled()){logger
.debug(" dao: initialize - DONE");}
709 // LogUtils.setLevel("org.hibernate.SQL", Level.WARN);
714 public <T
extends DescriptionElementBase
> long countDescriptionElementForTaxon(
715 UUID taxonUuid
, Set
<Feature
> features
, Class
<T
> type
) {
717 Query
<Long
> query
= prepareGetDescriptionElementForTaxon(taxonUuid
, features
, type
, null, null, "count(de)");
719 return query
.uniqueResult();
722 private <T
extends DescriptionElementBase
, R
extends Object
> Query
<R
> prepareGetDescriptionElementForTaxon(UUID taxonUuid
,
723 Set
<Feature
> features
, Class
<T
> type
, Integer pageSize
, Integer pageNumber
, String selectString
) {
725 String queryString
= "SELECT " + selectString
+ " FROM DescriptionElementBase AS de" +
726 " LEFT JOIN de.inDescription AS d" +
727 " LEFT JOIN d.taxon AS t" +
728 " WHERE d.class = 'TaxonDescription' AND t.uuid = :taxon_uuid ";
731 queryString
+= " and de.class = :type";
733 if (features
!= null && features
.size() > 0){
734 queryString
+= " and de.feature in (:features) ";
736 Query
<R
> query
= getSession().createQuery(queryString
);
738 query
.setParameter("taxon_uuid", taxonUuid
);
740 query
.setParameter("type", type
.getSimpleName());
742 if(features
!= null && features
.size() > 0){
743 query
.setParameterList("features", features
) ;
746 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
750 private Query
<SortableTaxonNodeQueryResult
> prepareGetIndividualAssociationForSpecimen(UUID specimenUuid
, UUID classificationUuid
, String selectString
) {
752 String queryString
= "SELECT " + selectString
+ " FROM DescriptionElementBase AS de" +
753 " LEFT JOIN de.inDescription AS d" +
754 " LEFT JOIN d.taxon AS t" +
755 " LEFT JOIN t.taxonNodes AS n" +
756 " LEFT JOIN de.associatedSpecimenOrObservation AS specimen ";
757 String classificationString
= "";
758 if (classificationUuid
!= null){
759 classificationString
= " LEFT JOIN n.classification AS c ";
761 String whereString
= " WHERE specimen.uuid = :specimen_uuid";
762 if (classificationUuid
!= null){
763 whereString
= whereString
+ " AND c.uuid = :classifcationUuid";
766 Query
<SortableTaxonNodeQueryResult
> query
= getSession().createQuery(queryString
+ classificationString
+ whereString
, SortableTaxonNodeQueryResult
.class);
768 query
.setParameter("specimen_uuid", specimenUuid
);
769 if (classificationUuid
!= null){
770 query
.setParameter("classifcationUuid", classificationUuid
);
777 public List
<Media
> listTaxonDescriptionMedia(UUID taxonUuid
,
778 Boolean limitToGalleries
, Set
<MarkerType
> markerTypes
,
779 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
781 AuditEvent auditEvent
= getAuditEventFromContext();
782 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
783 String queryString
= " SELECT media " +
784 getTaxonDescriptionMediaQueryString(
785 taxonUuid
, limitToGalleries
, markerTypes
);
788 // " ORDER BY index(media) " //not functional
791 Query
<Media
> query
= getSession().createQuery(queryString
, Media
.class);
793 setTaxonDescriptionMediaParameters(query
, taxonUuid
, limitToGalleries
, markerTypes
);
794 // addMarkerTypesCriterion(markerTypes, hql);
796 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
797 List
<Media
> results
= query
.list();
798 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
802 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid, boolean restrictToGalleries)");
807 public int countTaxonDescriptionMedia(UUID taxonUuid
,
808 Boolean limitToGalleries
, Set
<MarkerType
> markerTypes
) {
809 AuditEvent auditEvent
= getAuditEventFromContext();
810 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
811 String queryString
= " SELECT count(DISTINCT media) " +
812 getTaxonDescriptionMediaQueryString(
813 taxonUuid
, limitToGalleries
, markerTypes
);
815 Query
<Long
> query
= getSession().createQuery(queryString
, Long
.class);
816 setTaxonDescriptionMediaParameters(query
, taxonUuid
, limitToGalleries
, markerTypes
);
817 return query
.uniqueResult().intValue();
819 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid)");
824 private void setTaxonDescriptionMediaParameters(Query query
, UUID taxonUuid
, Boolean limitToGalleries
, Set
<MarkerType
> markerTypes
) {
825 if(taxonUuid
!= null){
826 query
.setParameter("uuid", taxonUuid
);
832 * @param restrictToGalleries
836 private String
getTaxonDescriptionMediaQueryString(UUID taxonUuid
,
837 Boolean restrictToGalleries
, Set
<MarkerType
> markerTypes
) {
838 String fromQueryString
=
839 " FROM DescriptionElementBase as deb INNER JOIN " +
840 " deb.inDescription as td "
841 + " INNER JOIN td.taxon as t "
842 + " JOIN deb.media as media "
843 + " LEFT JOIN td.markers marker ";
845 String whereQueryString
= " WHERE (1=1) ";
846 if (taxonUuid
!= null){
847 whereQueryString
+= " AND t.uuid = :uuid ";
849 if (restrictToGalleries
){
850 whereQueryString
+= " AND td.imageGallery is true ";
852 if (markerTypes
!= null && !markerTypes
.isEmpty()){
853 whereQueryString
+= " AND (1=0";
854 for (MarkerType markerType
: markerTypes
){
855 whereQueryString
+= " OR ( marker.markerType.id = " + markerType
.getId() + " AND marker.flag is true)";
858 whereQueryString
+= ") ";
861 return fromQueryString
+ whereQueryString
;
865 @SuppressWarnings("unchecked")
867 public List
<TermDto
> listNamedAreasInUse(boolean includeAllParents
, Integer pageSize
, Integer pageNumber
) {
869 // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
871 StringBuilder queryString
= new StringBuilder(
872 "SELECT DISTINCT a.id, a.partOf.id"
873 + " FROM Distribution AS d JOIN d.area AS a");
874 Query
<Object
[]> query
= getSession().createQuery(queryString
.toString(), Object
[].class);
876 List
<Object
[]> areasInUse
= query
.list();
877 List
<Object
[]> parentResults
= new ArrayList
<>();
879 if(!areasInUse
.isEmpty()) {
880 Set
<Object
> allAreaIds
= new HashSet
<>(areasInUse
.size());
882 if(includeAllParents
) {
883 // find all parent nodes
884 String allAreasQueryStr
= "select a.id, a.partOf.id from NamedArea as a";
885 query
= getSession().createQuery(allAreasQueryStr
, Object
[].class);
886 List
<Object
[]> allAreasResult
= query
.list();
887 Map
<Object
, Object
> allAreasMap
= ArrayUtils
.toMap(allAreasResult
.toArray());
889 Set
<Object
> parents
= new HashSet
<>();
891 for(Object
[] leaf
: areasInUse
) {
892 allAreaIds
.add(leaf
[0]);
893 Object parentId
= leaf
[1];
894 while (parentId
!= null) {
895 if(parents
.contains(parentId
)) {
896 // break if the parent already is in the set
899 parents
.add(parentId
);
900 parentId
= allAreasMap
.get(parentId
);
903 allAreaIds
.addAll(parents
);
905 // only add the ids found so far
906 for(Object
[] leaf
: areasInUse
) {
907 allAreaIds
.add(leaf
[0]);
911 // NOTE can't use "select new TermDto(distinct a.uuid, r , a.vocabulary.uuid) since we will get multiple
912 // rows for a term with multiple representations
913 String parentAreasQueryStr
= TermDto
.getTermDtoSelect("NamedArea")
914 + "where a.id in (:allAreaIds) order by a.idInVocabulary";
915 query
= getSession().createQuery(parentAreasQueryStr
, Object
[].class);
916 query
.setParameterList("allAreaIds", allAreaIds
);
918 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
919 parentResults
= query
.list();
921 List
<TermDto
> dtoList
= TermDto
.termDtoListFrom(parentResults
);