2 * Copyright (C) 2008 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
7 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.occurrence
;
9 import java
.util
.ArrayList
;
10 import java
.util
.Collection
;
11 import java
.util
.Collections
;
12 import java
.util
.HashSet
;
13 import java
.util
.List
;
15 import java
.util
.UUID
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.hibernate
.Criteria
;
19 import org
.hibernate
.Hibernate
;
20 import org
.hibernate
.Query
;
21 import org
.hibernate
.Session
;
22 import org
.hibernate
.criterion
.Disjunction
;
23 import org
.hibernate
.criterion
.ProjectionList
;
24 import org
.hibernate
.criterion
.Projections
;
25 import org
.hibernate
.criterion
.Restrictions
;
26 import org
.hibernate
.envers
.query
.AuditEntity
;
27 import org
.hibernate
.envers
.query
.AuditQuery
;
28 import org
.hibernate
.search
.FullTextSession
;
29 import org
.hibernate
.search
.Search
;
30 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
31 import org
.springframework
.stereotype
.Repository
;
33 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
34 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
35 import eu
.etaxonomy
.cdm
.model
.description
.IndividualsAssociation
;
36 import eu
.etaxonomy
.cdm
.model
.location
.Point
;
37 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
38 import eu
.etaxonomy
.cdm
.model
.molecular
.DnaSample
;
39 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
40 import eu
.etaxonomy
.cdm
.model
.name
.SpecimenTypeDesignation
;
41 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
42 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivationEvent
;
43 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
44 import eu
.etaxonomy
.cdm
.model
.occurrence
.DeterminationEvent
;
45 import eu
.etaxonomy
.cdm
.model
.occurrence
.FieldUnit
;
46 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
47 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationType
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
49 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
52 import eu
.etaxonomy
.cdm
.model
.view
.AuditEvent
;
53 import eu
.etaxonomy
.cdm
.persistence
.dao
.description
.IDescriptionDao
;
54 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.IdentifiableDaoBase
;
55 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.taxon
.TaxonDaoHibernateImpl
;
56 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.IHomotypicalGroupDao
;
57 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.ITaxonNameDao
;
58 import eu
.etaxonomy
.cdm
.persistence
.dao
.occurrence
.IOccurrenceDao
;
59 import eu
.etaxonomy
.cdm
.persistence
.dto
.SpecimenNodeWrapper
;
60 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
61 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
62 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
63 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
66 * @author a.babadshanjan
70 public class OccurrenceDaoHibernateImpl
71 extends IdentifiableDaoBase
<SpecimenOrObservationBase
>
72 implements IOccurrenceDao
{
74 private static final Logger logger
= Logger
.getLogger(TaxonDaoHibernateImpl
.class);
77 private IDescriptionDao descriptionDao
;
80 private ITaxonNameDao taxonNameDao
;
83 private IHomotypicalGroupDao homotypicalGroupDao
;
85 public OccurrenceDaoHibernateImpl() {
86 super(SpecimenOrObservationBase
.class);
87 indexedClasses
= new Class
[7];
88 indexedClasses
[0] = FieldUnit
.class;
89 indexedClasses
[1] = DerivedUnit
.class;
90 indexedClasses
[5] = DnaSample
.class;
94 public long countDerivationEvents(SpecimenOrObservationBase occurence
) {
95 checkNotInPriorView("OccurrenceDaoHibernateImpl.countDerivationEvents(SpecimenOrObservationBase occurence)");
96 Query query
= getSession().createQuery("select count(distinct derivationEvent) from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
97 query
.setParameter("occurence", occurence
);
99 return (Long
)query
.uniqueResult();
103 public long countDeterminations(SpecimenOrObservationBase occurrence
, TaxonBase taxonBase
) {
104 AuditEvent auditEvent
= getAuditEventFromContext();
105 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
106 Criteria criteria
= getCriteria(DeterminationEvent
.class);
107 if(occurrence
!= null) {
108 criteria
.add(Restrictions
.eq("identifiedUnit",occurrence
));
111 if(taxonBase
!= null) {
112 criteria
.add(Restrictions
.eq("taxon",taxonBase
));
115 criteria
.setProjection(Projections
.rowCount());
116 return (Long
)criteria
.uniqueResult();
118 AuditQuery query
= makeAuditQuery(DeterminationEvent
.class,auditEvent
);
120 if(occurrence
!= null) {
121 query
.add(AuditEntity
.relatedId("identifiedUnit").eq(occurrence
.getId()));
124 if(taxonBase
!= null) {
125 query
.add(AuditEntity
.relatedId("taxon").eq(taxonBase
.getId()));
127 query
.addProjection(AuditEntity
.id().count());
129 return (Long
)query
.getSingleResult();
134 public long countMedia(SpecimenOrObservationBase occurence
) {
135 checkNotInPriorView("OccurrenceDaoHibernateImpl.countMedia(SpecimenOrObservationBase occurence)");
136 Query query
= getSession().createQuery("select count(media) from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");
137 query
.setParameter("occurence", occurence
);
139 return (Long
)query
.uniqueResult();
143 public List
<DerivationEvent
> getDerivationEvents(SpecimenOrObservationBase occurence
, Integer pageSize
,Integer pageNumber
, List
<String
> propertyPaths
) {
144 checkNotInPriorView("OccurrenceDaoHibernateImpl.getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber)");
145 Query query
= getSession().createQuery("select distinct derivationEvent from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
146 query
.setParameter("occurence", occurence
);
148 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
150 @SuppressWarnings("unchecked")
151 List
<DerivationEvent
> result
= query
.list();
152 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
157 public List
<DeterminationEvent
> getDeterminations(SpecimenOrObservationBase occurrence
,
158 TaxonBase taxonBase
, Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
159 AuditEvent auditEvent
= getAuditEventFromContext();
160 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
161 Criteria criteria
= getSession().createCriteria(DeterminationEvent
.class);
162 if(occurrence
!= null) {
163 criteria
.add(Restrictions
.eq("identifiedUnit",occurrence
));
166 if(taxonBase
!= null) {
167 criteria
.add(Restrictions
.eq("taxon",taxonBase
));
170 addPageSizeAndNumber(criteria
, pageSize
, pageNumber
);
172 @SuppressWarnings("unchecked")
173 List
<DeterminationEvent
> result
= criteria
.list();
174 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
177 AuditQuery query
= getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent
.class,auditEvent
.getRevisionNumber());
178 if(occurrence
!= null) {
179 query
.add(AuditEntity
.relatedId("identifiedUnit").eq(occurrence
.getId()));
182 if(taxonBase
!= null) {
183 query
.add(AuditEntity
.relatedId("taxon").eq(taxonBase
.getId()));
185 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
187 @SuppressWarnings("unchecked")
188 List
<DeterminationEvent
> result
= query
.getResultList();
189 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
195 public List
<Media
> getMedia(SpecimenOrObservationBase occurence
,
196 Integer pageSize
, Integer pageNumber
, List
<String
> propertyPaths
) {
197 checkNotInPriorView("OccurrenceDaoHibernateImpl.getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths)");
198 Query query
= getSession().createQuery(
200 + " FROM SpecimenOrObservationBase occurence "
201 + " JOIN occurence.media media "
202 + " WHERE occurence = :occurence");
203 query
.setParameter("occurence", occurence
);
205 addPageSizeAndNumber(query
, pageSize
, pageNumber
);
207 @SuppressWarnings("unchecked")
208 List
<Media
> results
= query
.list();
209 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
214 public void rebuildIndex() {
215 FullTextSession fullTextSession
= Search
.getFullTextSession(getSession());
217 for(SpecimenOrObservationBase
<?
> occurrence
: list(null,null)) { // re-index all taxon base
219 for(DeterminationEvent determination
: occurrence
.getDeterminations()) {
220 Hibernate
.initialize(determination
.getActor());
221 Hibernate
.initialize(determination
.getTaxon());
223 Hibernate
.initialize(occurrence
.getDefinition());
224 if(occurrence
instanceof DerivedUnit
) {
225 DerivedUnit derivedUnit
= (DerivedUnit
) occurrence
;
226 Hibernate
.initialize(derivedUnit
.getCollection());
227 if(derivedUnit
.getCollection() != null) {
228 Hibernate
.initialize(derivedUnit
.getCollection().getSuperCollection());
229 Hibernate
.initialize(derivedUnit
.getCollection().getInstitute());
231 Hibernate
.initialize(derivedUnit
.getStoredUnder());
232 SpecimenOrObservationBase
<?
> original
= derivedUnit
.getOriginalUnit();
233 if(original
!= null && original
.isInstanceOf(FieldUnit
.class)) {
234 FieldUnit fieldUnit
= CdmBase
.deproxy(original
, FieldUnit
.class);
235 Hibernate
.initialize(fieldUnit
.getGatheringEvent());
236 if(fieldUnit
.getGatheringEvent() != null) {
237 Hibernate
.initialize(fieldUnit
.getGatheringEvent().getActor());
241 fullTextSession
.index(occurrence
);
243 fullTextSession
.flushToIndexes();
247 public long count(Class
<?
extends SpecimenOrObservationBase
> clazz
, TaxonName determinedAs
) {
249 Criteria criteria
= getCriteria(clazz
);
251 criteria
.createCriteria("determinations").add(Restrictions
.eq("taxonName", determinedAs
));
252 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
253 return (Long
)criteria
.uniqueResult();
257 public List
<SpecimenOrObservationBase
> list(Class
<?
extends SpecimenOrObservationBase
> clazz
, TaxonName determinedAs
,
258 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
259 Criteria criteria
= getCriteria(clazz
);
261 criteria
.createCriteria("determinations").add(Restrictions
.eq("taxonName", determinedAs
));
263 addPageSizeAndNumber(criteria
, pageSize
, pageNumber
);
264 addOrder(criteria
,orderHints
);
266 @SuppressWarnings({ "unchecked", "rawtypes" })
267 List
<SpecimenOrObservationBase
> results
= criteria
.list();
268 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
273 public long count(Class
<?
extends SpecimenOrObservationBase
> clazz
, TaxonBase determinedAs
) {
275 Criteria criteria
= getCriteria(clazz
);
277 criteria
.createCriteria("determinations").add(Restrictions
.eq("taxon", determinedAs
));
278 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
279 return (Long
)criteria
.uniqueResult();
284 public List
<SpecimenOrObservationBase
> list(Class
<?
extends SpecimenOrObservationBase
> clazz
, TaxonBase determinedAs
,
285 Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
287 Criteria criteria
= getCriteria(clazz
);
289 criteria
.createCriteria("determinations").add(Restrictions
.eq("taxon", determinedAs
));
291 addPageSizeAndNumber(criteria
, pageSize
, pageNumber
);
292 addOrder(criteria
,orderHints
);
294 @SuppressWarnings({ "unchecked", "rawtypes" })
295 List
<SpecimenOrObservationBase
> results
= criteria
.list();
296 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
301 public <T
extends SpecimenOrObservationBase
> List
<UuidAndTitleCache
<SpecimenOrObservationBase
>> findOccurrencesUuidAndTitleCache(
302 Class
<T
> clazz
, String queryString
, String significantIdentifier
, SpecimenOrObservationType recordBasis
,
303 Taxon associatedTaxon
, TaxonName associatedTaxonName
, MatchMode matchmode
, Integer limit
, Integer start
,
304 List
<OrderHint
> orderHints
) {
305 Criteria criteria
= createFindOccurrenceCriteria(clazz
, queryString
, significantIdentifier
, recordBasis
,
306 associatedTaxon
, associatedTaxonName
, matchmode
, limit
, start
, orderHints
, null);
308 ProjectionList projectionList
= Projections
.projectionList();
309 projectionList
.add(Projections
.property("uuid"));
310 projectionList
.add(Projections
.property("id"));
311 projectionList
.add(Projections
.property("titleCache"));
312 criteria
.setProjection(projectionList
);
314 @SuppressWarnings("unchecked")
315 List
<Object
[]> result
= criteria
.list();
316 List
<UuidAndTitleCache
<SpecimenOrObservationBase
>> uuidAndTitleCacheList
= new ArrayList
<>();
317 for(Object
[] object
: result
){
318 uuidAndTitleCacheList
.add(new UuidAndTitleCache
<>((UUID
) object
[0],(Integer
) object
[1], (String
) object
[2]));
320 return uuidAndTitleCacheList
;
322 return Collections
.emptyList();
327 public <T
extends SpecimenOrObservationBase
> List
<T
> findOccurrences(Class
<T
> clazz
, String queryString
,
328 String significantIdentifier
, SpecimenOrObservationType recordBasis
, Taxon associatedTaxon
, TaxonName associatedTaxonName
,
329 MatchMode matchmode
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
331 Criteria criteria
= createFindOccurrenceCriteria(clazz
, queryString
, significantIdentifier
, recordBasis
,
332 associatedTaxon
, associatedTaxonName
, matchmode
, limit
, start
, orderHints
, propertyPaths
);
334 @SuppressWarnings("unchecked")
335 List
<T
> results
= criteria
.list();
336 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
339 return Collections
.emptyList();
343 private <T
extends SpecimenOrObservationBase
> Criteria
createFindOccurrenceCriteria(Class
<T
> clazz
, String queryString
,
344 String significantIdentifier
, SpecimenOrObservationType recordBasis
, Taxon associatedTaxon
,
345 TaxonName associatedTaxonName
, MatchMode matchmode
, Integer limit
,
346 Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
347 Criteria criteria
= null;
350 criteria
= getSession().createCriteria(type
);
352 criteria
= getSession().createCriteria(clazz
);
356 if (queryString
!= null) {
357 if(matchmode
== null) {
358 matchmode
= MatchMode
.ANYWHERE
;
359 criteria
.add(Restrictions
.ilike("titleCache", matchmode
.queryStringFrom(queryString
)));
360 } else if(matchmode
== MatchMode
.BEGINNING
) {
361 criteria
.add(Restrictions
.ilike("titleCache", matchmode
.queryStringFrom(queryString
), org
.hibernate
.criterion
.MatchMode
.START
));
362 } else if(matchmode
== MatchMode
.END
) {
363 criteria
.add(Restrictions
.ilike("titleCache", matchmode
.queryStringFrom(queryString
), org
.hibernate
.criterion
.MatchMode
.END
));
364 } else if(matchmode
== MatchMode
.EXACT
) {
365 criteria
.add(Restrictions
.ilike("titleCache", matchmode
.queryStringFrom(queryString
), org
.hibernate
.criterion
.MatchMode
.EXACT
));
367 criteria
.add(Restrictions
.ilike("titleCache", matchmode
.queryStringFrom(queryString
), org
.hibernate
.criterion
.MatchMode
.ANYWHERE
));
371 //significant identifier
372 if (significantIdentifier
!= null) {
373 criteria
.add(Restrictions
.or(Restrictions
.ilike("accessionNumber", significantIdentifier
),
374 Restrictions
.ilike("catalogNumber", significantIdentifier
), Restrictions
.ilike("barcode", significantIdentifier
)));
377 //recordBasis/SpecimenOrObservationType
378 Set
<SpecimenOrObservationType
> typeAndSubtypes
= new HashSet
<>();
379 if(recordBasis
==null){
381 SpecimenOrObservationType
[] values
= SpecimenOrObservationType
.values();
382 for (SpecimenOrObservationType specimenOrObservationType
: values
) {
383 typeAndSubtypes
.add(specimenOrObservationType
);
387 typeAndSubtypes
= recordBasis
.getGeneralizationOf(true);
388 typeAndSubtypes
.add(recordBasis
);
390 criteria
.add(Restrictions
.in("recordBasis", typeAndSubtypes
));
392 Set
<UUID
> associationUuids
= new HashSet
<>();
394 if(associatedTaxon
!=null){
395 List
<UuidAndTitleCache
<SpecimenOrObservationBase
>> associatedTaxaList
= listUuidAndTitleCacheByAssociatedTaxon(clazz
, associatedTaxon
, limit
, start
, orderHints
);
396 if(associatedTaxaList
!=null){
397 for (UuidAndTitleCache
<SpecimenOrObservationBase
> uuidAndTitleCache
: associatedTaxaList
) {
398 associationUuids
.add(uuidAndTitleCache
.getUuid());
402 //taxon name associations
403 else if(associatedTaxonName
!=null){
404 List
<?
extends SpecimenOrObservationBase
> associatedTaxaList
= listByAssociatedTaxonName(clazz
, associatedTaxonName
, limit
, start
, orderHints
, propertyPaths
);
405 if(associatedTaxaList
!=null){
406 for (SpecimenOrObservationBase
<?
> specimenOrObservationBase
: associatedTaxaList
) {
407 associationUuids
.add(specimenOrObservationBase
.getUuid());
411 if(associatedTaxon
!=null || associatedTaxonName
!=null){
412 if(!associationUuids
.isEmpty()){
413 criteria
.add(Restrictions
.in("uuid", associationUuids
));
421 criteria
.setFirstResult(start
);
423 criteria
.setFirstResult(0);
425 criteria
.setMaxResults(limit
);
428 if(orderHints
!=null){
429 addOrder(criteria
,orderHints
);
436 public <T
extends SpecimenOrObservationBase
> long countOccurrences(Class
<T
> clazz
, String queryString
,
437 String significantIdentifier
, SpecimenOrObservationType recordBasis
, Taxon associatedTaxon
, TaxonName associatedTaxonName
,
438 MatchMode matchmode
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
440 Criteria criteria
= createFindOccurrenceCriteria(clazz
, queryString
, significantIdentifier
, recordBasis
,
441 associatedTaxon
, associatedTaxonName
, matchmode
, limit
, start
, orderHints
, propertyPaths
);
444 criteria
.setProjection(Projections
.rowCount());
445 return (Long
)criteria
.uniqueResult();
452 public List
<UuidAndTitleCache
<DerivedUnit
>> getDerivedUnitUuidAndTitleCache(Integer limit
, String pattern
) {
453 List
<UuidAndTitleCache
<DerivedUnit
>> list
= new ArrayList
<>();
454 Session session
= getSession();
455 String hql
= "SELECT uuid, id, titleCache "
456 + " FROM " + type
.getSimpleName()
457 + " WHERE NOT dtype = " + FieldUnit
.class.getSimpleName();
459 if (pattern
!= null){
460 pattern
= pattern
.replace("*", "%");
461 pattern
= pattern
.replace("?", "_");
462 pattern
= pattern
+ "%";
463 query
= session
.createQuery(hql
+" AND titleCache like :pattern");
464 query
.setParameter("pattern", pattern
);
466 query
= session
.createQuery(hql
);
469 query
.setMaxResults(limit
);
472 @SuppressWarnings("unchecked")
473 List
<Object
[]> result
= query
.list();
475 for(Object
[] object
: result
){
476 list
.add(new UuidAndTitleCache
<DerivedUnit
>(DerivedUnit
.class, (UUID
) object
[0], (Integer
)object
[1], (String
) object
[2]));
483 public List
<UuidAndTitleCache
<FieldUnit
>> getFieldUnitUuidAndTitleCache() {
484 List
<UuidAndTitleCache
<FieldUnit
>> list
= new ArrayList
<>();
485 Session session
= getSession();
487 Query query
= session
.createQuery("select uuid, id, titleCache from " + type
.getSimpleName() + " where dtype = " + FieldUnit
.class.getSimpleName());
489 @SuppressWarnings("unchecked")
490 List
<Object
[]> result
= query
.list();
492 for(Object
[] object
: result
){
493 list
.add(new UuidAndTitleCache
<FieldUnit
>(FieldUnit
.class, (UUID
) object
[0], (Integer
)object
[1], (String
) object
[2]));
500 public <T
extends SpecimenOrObservationBase
> List
<T
> listByAssociatedTaxonName(Class
<T
> type
,
501 TaxonName associatedTaxonName
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
503 @SuppressWarnings("rawtypes")
504 Set
<SpecimenOrObservationBase
> setOfAll
= new HashSet
<>();
506 // A Taxon name may be referenced by the DeterminationEvent of the SpecimenOrObservationBase
507 @SuppressWarnings("rawtypes")
508 List
<SpecimenOrObservationBase
> byDetermination
= list(type
, associatedTaxonName
, null, 0, null, null);
509 setOfAll
.addAll(byDetermination
);
511 if(setOfAll
.size() == 0){
512 // no need querying the data base
513 return new ArrayList
<T
>();
518 " FROM SpecimenOrObservationBase sob" +
519 " WHERE sob in (:setOfAll)";
521 if(type
!= null && !type
.equals(SpecimenOrObservationBase
.class)){
522 queryString
+= " AND sob.class = :type";
524 queryString
+= orderByClause("sob", orderHints
);
526 Query query
= getSession().createQuery(queryString
);
527 query
.setParameterList("setOfAll", setOfAll
);
529 if(type
!= null && !type
.equals(SpecimenOrObservationBase
.class)){
530 query
.setParameter("type", type
.getSimpleName());
533 addLimitAndStart(query
, limit
, start
);
535 @SuppressWarnings("unchecked")
536 List
<T
> results
= query
.list();
537 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
541 private List
<SpecimenNodeWrapper
> querySpecimen(Query query
, List
<UUID
> taxonNodeUuids
,
542 Integer limit
, Integer start
){
543 query
.setParameterList("taxonNodeUuids", taxonNodeUuids
);
545 addLimitAndStart(query
, limit
, start
);
547 List
<SpecimenNodeWrapper
> list
= new ArrayList
<>();
548 @SuppressWarnings("unchecked")
549 List
<Object
[]> result
= query
.list();
550 for(Object
[] object
: result
){
551 SpecimenNodeWrapper wrapper
= new SpecimenNodeWrapper(
552 new UuidAndTitleCache
<>(
556 (SpecimenOrObservationType
)object
[3],
557 new TaxonNodeDto((TaxonNode
)object
[4]));
558 if(object
.length
>5) {
559 wrapper
.setTaxonDescriptionUuid((UUID
)object
[5]);
566 private List
<SpecimenNodeWrapper
> queryIndividualAssociatedSpecimen(List
<UUID
> taxonNodeUuids
,
567 Integer limit
, Integer start
){
568 String queryString
= "SELECT "
569 + "de.associatedSpecimenOrObservation.uuid, "
570 + "de.associatedSpecimenOrObservation.id, "
571 + "de.associatedSpecimenOrObservation.titleCache, "
572 + "de.associatedSpecimenOrObservation.recordBasis, "
575 + "FROM DescriptionElementBase AS de "
576 + "LEFT JOIN de.inDescription AS d "
577 + "LEFT JOIN d.taxon AS t "
578 + "JOIN t.taxonNodes AS tn "
579 + "WHERE d.class = 'TaxonDescription' "
580 + "AND tn.uuid in (:taxonNodeUuids) "
582 Query query
= getSession().createQuery(queryString
);
583 return querySpecimen(query
, taxonNodeUuids
, limit
, start
);
586 private List
<SpecimenNodeWrapper
> queryTypeSpecimen(List
<UUID
> taxonNodeUuids
,
587 Integer limit
, Integer start
){
588 String queryString
= "SELECT "
589 + "td.typeSpecimen.uuid, "
590 + "td.typeSpecimen.id, "
591 + "td.typeSpecimen.titleCache, "
592 + "td.typeSpecimen.recordBasis, "
594 + "FROM SpecimenTypeDesignation AS td "
595 + "LEFT JOIN td.typifiedNames AS tn "
596 + "LEFT JOIN tn.taxonBases AS t "
597 + "JOIN t.taxonNodes AS tn "
598 + "WHERE tn.uuid in (:taxonNodeUuids) "
600 Query query
= getSession().createQuery(queryString
);
601 return querySpecimen(query
, taxonNodeUuids
, limit
, start
);
604 private List
<SpecimenNodeWrapper
> queryTaxonDeterminations(List
<UUID
> taxonNodeUuids
,
605 Integer limit
, Integer start
){
606 String queryString
= "SELECT "
607 + "det.identifiedUnit.uuid, "
608 + "det.identifiedUnit.id, "
609 + "det.identifiedUnit.titleCache, "
610 + "det.identifiedUnit.recordBasis, "
612 + "FROM DeterminationEvent AS det "
613 + "LEFT JOIN det.taxon AS t "
614 + "JOIN t.taxonNodes AS tn "
615 + "WHERE tn.uuid in (:taxonNodeUuids) "
617 Query query
= getSession().createQuery(queryString
);
618 return querySpecimen(query
, taxonNodeUuids
, limit
, start
);
621 private List
<SpecimenNodeWrapper
> queryTaxonNameDeterminations(List
<UUID
> taxonNodeUuids
,
622 Integer limit
, Integer start
){
623 String queryString
= "SELECT "
624 + "det.identifiedUnit.uuid, "
625 + "det.identifiedUnit.id, "
626 + "det.identifiedUnit.titleCache, "
627 + "det.identifiedUnit.recordBasis, "
629 + "FROM DeterminationEvent AS det "
630 + "LEFT JOIN det.taxonName AS n "
631 + "LEFT JOIN n.taxonBases AS t "
632 + "JOIN t.taxonNodes AS tn "
633 + "WHERE tn.uuid in (:taxonNodeUuids) "
635 Query query
= getSession().createQuery(queryString
);
636 return querySpecimen(query
, taxonNodeUuids
, limit
, start
);
640 public Collection
<SpecimenNodeWrapper
> listUuidAndTitleCacheByAssociatedTaxon(List
<UUID
> taxonNodeUuids
,
641 Integer limit
, Integer start
){
643 Set
<SpecimenNodeWrapper
> testSet
= new HashSet();
645 testSet
.addAll(queryIndividualAssociatedSpecimen(taxonNodeUuids
, limit
, start
));
646 testSet
.addAll(queryTaxonDeterminations(taxonNodeUuids
, limit
, start
));
647 testSet
.addAll(queryTaxonNameDeterminations(taxonNodeUuids
, limit
, start
));
648 testSet
.addAll(queryTypeSpecimen(taxonNodeUuids
, limit
, start
));
650 Collection
<SpecimenNodeWrapper
> wrappers
= new HashSet
<>();
651 wrappers
.addAll(testSet
);
656 public <T
extends SpecimenOrObservationBase
> List
<UuidAndTitleCache
<SpecimenOrObservationBase
>> listUuidAndTitleCacheByAssociatedTaxon(Class
<T
> clazz
, Taxon associatedTaxon
,
657 Integer limit
, Integer start
, List
<OrderHint
> orderHints
){
658 Query query
= createSpecimenQuery("sob.uuid, sob.id, sob.titleCache", clazz
, associatedTaxon
, limit
, start
, orderHints
);
660 return Collections
.emptyList();
662 List
<UuidAndTitleCache
<SpecimenOrObservationBase
>> list
= new ArrayList
<>();
663 @SuppressWarnings("unchecked")
664 List
<Object
[]> result
= query
.list();
665 for(Object
[] object
: result
){
666 list
.add(new UuidAndTitleCache
<>((UUID
) object
[0],(Integer
) object
[1], (String
) object
[2]));
672 public <T
extends SpecimenOrObservationBase
> List
<T
> listByAssociatedTaxon(Class
<T
> clazz
,
673 Taxon associatedTaxon
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
674 Query query
= createSpecimenQuery("sob", clazz
, associatedTaxon
, limit
, start
, orderHints
);
676 return Collections
.emptyList();
678 @SuppressWarnings("unchecked")
679 List
<T
> results
= query
.list();
680 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
684 private <T
extends SpecimenOrObservationBase
> Query
createSpecimenQuery(String select
, Class
<T
> clazz
,
685 Taxon associatedTaxon
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
){
686 // Set<SpecimenOrObservationBase> setOfAll = new HashSet<>();
687 Set
<Integer
> setOfAllIds
= new HashSet
<>();
689 Criteria criteria
= null;
691 criteria
= getSession().createCriteria(type
, "specimen");
693 criteria
= getSession().createCriteria(clazz
, "specimen");
696 Disjunction determinationOr
= Restrictions
.disjunction();
698 // A Taxon may be referenced by the DeterminationEvent of the SpecimenOrObservationBase
699 Criteria determinationsCriteria
= criteria
.createCriteria("determinations");
701 determinationOr
.add(Restrictions
.eq("taxon", associatedTaxon
));
702 //check also for synonyms
703 for (Synonym synonym
: associatedTaxon
.getSynonyms()) {
704 determinationOr
.add(Restrictions
.eq("taxon", synonym
));
707 //check also for name determinations
708 determinationOr
.add(Restrictions
.eq("taxonName", associatedTaxon
.getName()));
709 for (TaxonName synonymName
: associatedTaxon
.getSynonymNames()) {
710 determinationOr
.add(Restrictions
.eq("taxonName", synonymName
));
713 determinationsCriteria
.add(determinationOr
);
717 criteria
.setFirstResult(start
);
719 criteria
.setFirstResult(0);
721 criteria
.setMaxResults(limit
);
723 criteria
.setProjection(Projections
.property("id"));
725 addOrder(criteria
,orderHints
);
727 @SuppressWarnings("unchecked")
728 List
<Integer
> detResults
= criteria
.list();
729 setOfAllIds
.addAll(detResults
);
731 // The IndividualsAssociation elements in a TaxonDescription contain DerivedUnits
732 setOfAllIds
.addAll(descriptionDao
.getIndividualAssociationSpecimenIDs(
733 associatedTaxon
.getUuid(), null, null, 0, null));
736 // SpecimenTypeDesignations may be associated with the TaxonName.
737 setOfAllIds
.addAll(taxonNameDao
.getTypeSpecimenIdsForTaxonName(
738 associatedTaxon
.getName(), null, null, null));
740 // SpecimenTypeDesignations may be associated with any HomotypicalGroup related to the specific Taxon.
741 //TODO adapt to set of ids
742 for(HomotypicalGroup homotypicalGroup
: associatedTaxon
.getHomotypicSynonymyGroups()) {
743 List
<SpecimenTypeDesignation
> byHomotypicalGroup
= homotypicalGroupDao
.getTypeDesignations(homotypicalGroup
, SpecimenTypeDesignation
.class, null, null, 0, null);
744 for (SpecimenTypeDesignation specimenTypeDesignation
: byHomotypicalGroup
) {
745 if (specimenTypeDesignation
.getTypeSpecimen() != null){
746 setOfAllIds
.add(specimenTypeDesignation
.getTypeSpecimen().getId());
751 if(setOfAllIds
.size() == 0){
752 // no need querying the data base
758 " from SpecimenOrObservationBase sob" +
759 " where sob.id in (:setOfAllIds)";
761 if(clazz
!= null && !clazz
.equals(SpecimenOrObservationBase
.class)){
762 queryString
+= " and sob.class = :type ";
765 if(orderHints
!= null && orderHints
.size() > 0){
766 queryString
+= " order by ";
767 String orderStr
= "";
768 for(OrderHint orderHint
: orderHints
){
769 if(orderStr
.length() > 0){
772 queryString
+= "sob." + orderHint
.getPropertyName() + " " + orderHint
.getSortOrder().toHql();
774 queryString
+= orderStr
;
777 Query query
= getSession().createQuery(queryString
);
778 query
.setParameterList("setOfAllIds", setOfAllIds
);
780 if(clazz
!= null && !clazz
.equals(SpecimenOrObservationBase
.class)){
781 query
.setParameter("type", clazz
.getSimpleName());
784 addLimitAndStart(query
, limit
, start
);
790 public Collection
<SpecimenOrObservationBase
> listBySpecimenOrObservationType(SpecimenOrObservationType type
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
791 String queryString
= "FROM SpecimenOrObservationBase specimens "
792 + " WHERE specimens.recordBasis = :type ";
794 queryString
+= orderByClause("specimens", orderHints
);
796 Query query
= getSession().createQuery(queryString
);
797 query
.setParameter("type", type
);
799 addLimitAndStart(query
, limit
, start
);
801 @SuppressWarnings({ "unchecked", "rawtypes" })
802 List
<SpecimenOrObservationBase
> results
= query
.list();
803 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
809 public Collection
<DeterminationEvent
> listDeterminationEvents(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
810 String queryString
= "FROM DeterminationEvent determination "
811 + " WHERE determination.identifiedUnit = :specimen";
813 queryString
+= orderByClause("determination", orderHints
);
815 Query query
= getSession().createQuery(queryString
);
816 query
.setParameter("specimen", specimen
);
818 addLimitAndStart(query
, limit
, start
);
820 @SuppressWarnings("unchecked")
821 List
<DeterminationEvent
> results
= query
.list();
822 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
827 public Collection
<SpecimenTypeDesignation
> listTypeDesignations(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
828 String queryString
= "FROM SpecimenTypeDesignation designations "
829 + " WHERE designations.typeSpecimen = :specimen";
831 queryString
+= orderByClause("designations", orderHints
);
833 Query query
= getSession().createQuery(queryString
);
834 query
.setParameter("specimen", specimen
);
836 addLimitAndStart(query
, limit
, start
);
838 @SuppressWarnings("unchecked")
839 List
<SpecimenTypeDesignation
> results
= query
.list();
840 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
846 public Collection
<IndividualsAssociation
> listIndividualsAssociations(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
847 //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements
848 String queryString
= "FROM IndividualsAssociation associations WHERE associations.associatedSpecimenOrObservation = :specimen";
850 queryString
+= orderByClause("associations", orderHints
);
852 Query query
= getSession().createQuery(queryString
);
853 query
.setParameter("specimen", specimen
);
855 addLimitAndStart(query
, limit
, start
);
857 @SuppressWarnings("unchecked")
858 List
<IndividualsAssociation
> results
= query
.list();
859 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
864 public Collection
<DescriptionBase
<?
>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase
<?
> specimen
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
865 //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements
866 String queryString
= "FROM DescriptionBase descriptions "
867 + " WHERE descriptions.describedSpecimenOrObservation = :specimen";
869 queryString
+= orderByClause("descriptions", orderHints
);
871 Query query
= getSession().createQuery(queryString
);
872 query
.setParameter("specimen", specimen
);
874 addLimitAndStart(query
, limit
, start
);
876 @SuppressWarnings("unchecked")
877 List
<DescriptionBase
<?
>> results
= query
.list();
878 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
886 public List
<FieldUnit
> findFieldUnitsForGatheringEvent(UUID gatheringEventUuid
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
887 String queryString
= "FROM SpecimenOrObservationBase sob "
888 + "WHERE sob.gatheringEvent.uuid = :gatheringEventUuid";
890 queryString
+= orderByClause("sob", orderHints
);
892 Query query
= getSession().createQuery(queryString
);
893 query
.setParameter("gatheringEventUuid", gatheringEventUuid
);
895 addLimitAndStart(query
, limit
, start
);
897 @SuppressWarnings("unchecked")
898 List
<FieldUnit
> results
= query
.list();
899 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
908 public DnaSample
findByGeneticAccessionNumber(String accessionNumberString
, List
<String
> propertyPaths
) {
909 String queryString
= "SELECT dnaSample FROM DnaSample as dnaSample join dnaSample.sequences as sequences WITH sequences.geneticAccessionNumber LIKE :accessionNumberString";
910 Query query
= getSession().createQuery(queryString
);
911 query
.setParameter("accessionNumberString", accessionNumberString
);
912 @SuppressWarnings("unchecked")
913 List
<DnaSample
> dnaSamples
= query
.list();
914 defaultBeanInitializer
.initializeAll(dnaSamples
, propertyPaths
);
917 if (dnaSamples
.isEmpty()){
918 logger
.debug("there is no dnaSample for genetic accession number " + accessionNumberString
+ " this should not happen.");
920 }else if (dnaSamples
.size() == 1){
921 return dnaSamples
.get(0);
923 logger
.debug("there are more than one dnaSample for genetic accession number " + accessionNumberString
+ " this should not happen.");
935 public long countByGeneticAccessionNumber(String accessionNumberString
) {
936 String queryString
= "SELECT count(dnaSample) FROM DnaSample dnaSample JOIN dnaSample.sequences sequence WHERE sequence.geneticAccessionNumber LIKE :accessionNumberString";
937 Query query
= getSession().createQuery(queryString
);
938 query
.setParameter("accessionNumberString", accessionNumberString
);
939 @SuppressWarnings("unchecked")
940 List
<DerivedUnit
> dnaSamples
= query
.list();
941 long result
= (long)query
.uniqueResult();
950 private void extractDeterminedOriginals(List
<DerivedUnit
> samples
, List
<DerivedUnit
> results
) {
951 for (DerivedUnit sample
:samples
){
952 if (sample
.getDeterminations() != null && !sample
.getDeterminations().isEmpty()){
955 if (sample
instanceof DerivedUnit
){
956 Set
<SpecimenOrObservationBase
> originals
= sample
.getDerivedFrom().getOriginals();
957 List
<DerivedUnit
> originalDerivedUnits
= new ArrayList();
958 for (SpecimenOrObservationBase original
:originals
){
959 if (original
instanceof DerivedUnit
){
960 originalDerivedUnits
.add((DerivedUnit
)original
);
963 if(!originalDerivedUnits
.isEmpty()){
964 extractDeterminedOriginals(originalDerivedUnits
, results
);
975 public List
<SpecimenOrObservationBase
> findOriginalsForDerivedUnit(UUID derivedUnitUuid
, List
<String
> propertyPaths
) {
976 String queryString
= "SELECT DISTINCT o FROM DerivedUnit du"
977 + " JOIN du.derivedFrom.originals o WHERE du.uuid LIKE :derivedUnitUuid";
978 Query query
= getSession().createQuery(queryString
);
979 query
.setParameter("derivedUnitUuid", derivedUnitUuid
);
980 @SuppressWarnings("unchecked")
981 List
<SpecimenOrObservationBase
> results
= query
.list();
982 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
990 public List
<Point
> findPointsForFieldUnitList(List
<UUID
> fieldUnitUuids
) {
991 String queryString
= "SELECT DISTINCT fu.gatheringEvent.exactLocation FROM FieldUnit fu"
992 + " WHERE fu.uuid IN (:fieldUnitUuids)";
993 Query query
= getSession().createQuery(queryString
);
994 query
.setParameterList("fieldUnitUuids", fieldUnitUuids
);
995 @SuppressWarnings("unchecked")
996 List
<Point
> results
= query
.list();