merge-update from trunk
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / occurrence / OccurrenceDaoHibernateImpl.java
1 /**
2 * Copyright (C) 2008 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 */
6
7 package eu.etaxonomy.cdm.persistence.dao.hibernate.occurrence;
8
9 import java.util.ArrayList;
10 import java.util.Collection;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Set;
14 import java.util.UUID;
15
16 import org.apache.log4j.Logger;
17 import org.hibernate.Criteria;
18 import org.hibernate.Hibernate;
19 import org.hibernate.Query;
20 import org.hibernate.Session;
21 import org.hibernate.criterion.Projections;
22 import org.hibernate.criterion.Restrictions;
23 import org.hibernate.envers.query.AuditEntity;
24 import org.hibernate.envers.query.AuditQuery;
25 import org.hibernate.search.FullTextSession;
26 import org.hibernate.search.Search;
27 import org.springframework.beans.factory.annotation.Autowired;
28 import org.springframework.stereotype.Repository;
29
30 import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
31 import eu.etaxonomy.cdm.model.description.DescriptionBase;
32 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
33 import eu.etaxonomy.cdm.model.media.Media;
34 import eu.etaxonomy.cdm.model.molecular.DnaSample;
35 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
36 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
37 import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
38 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
39 import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
40 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
41 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
42 import eu.etaxonomy.cdm.model.taxon.Taxon;
43 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
44 import eu.etaxonomy.cdm.model.view.AuditEvent;
45 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
46 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
47 import eu.etaxonomy.cdm.persistence.dao.hibernate.taxon.TaxonDaoHibernateImpl;
48 import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
49 import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
50 import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
51 import eu.etaxonomy.cdm.persistence.query.OrderHint;
52
53 /**
54 * @author a.babadshanjan
55 * @created 01.09.2008
56 */
57 @Repository
58 public class OccurrenceDaoHibernateImpl extends IdentifiableDaoBase<SpecimenOrObservationBase> implements IOccurrenceDao {
59
60 @SuppressWarnings("unused")
61 private static final Logger logger = Logger.getLogger(TaxonDaoHibernateImpl.class);
62
63 @Autowired
64 private IDescriptionDao descriptionDao;
65
66 @Autowired
67 private ITaxonNameDao taxonNameDao;
68
69 @Autowired
70 private IHomotypicalGroupDao homotypicalGroupDao;
71
72 public OccurrenceDaoHibernateImpl() {
73 super(SpecimenOrObservationBase.class);
74 indexedClasses = new Class[7];
75 indexedClasses[0] = FieldUnit.class;
76 indexedClasses[1] = DerivedUnit.class;
77 indexedClasses[5] = DnaSample.class;
78 }
79
80 /* (non-Javadoc)
81 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countDerivationEvents(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
82 */
83 @Override
84 public int countDerivationEvents(SpecimenOrObservationBase occurence) {
85 checkNotInPriorView("OccurrenceDaoHibernateImpl.countDerivationEvents(SpecimenOrObservationBase occurence)");
86 Query query = getSession().createQuery("select count(distinct derivationEvent) from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
87 query.setParameter("occurence", occurence);
88
89 return ((Long)query.uniqueResult()).intValue();
90 }
91
92 /* (non-Javadoc)
93 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase)
94 */
95 @Override
96 public int countDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase) {
97 AuditEvent auditEvent = getAuditEventFromContext();
98 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
99 Criteria criteria = getSession().createCriteria(DeterminationEvent.class);
100 if(occurrence != null) {
101 criteria.add(Restrictions.eq("identifiedUnit",occurrence));
102 }
103
104 if(taxonBase != null) {
105 criteria.add(Restrictions.eq("taxon",taxonBase));
106 }
107
108 criteria.setProjection(Projections.rowCount());
109 return ((Number)criteria.uniqueResult()).intValue();
110 } else {
111 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());
112
113 if(occurrence != null) {
114 query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));
115 }
116
117 if(taxonBase != null) {
118 query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));
119 }
120 query.addProjection(AuditEntity.id().count("id"));
121
122 return ((Long)query.getSingleResult()).intValue();
123 }
124 }
125
126 /* (non-Javadoc)
127 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countMedia(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
128 */
129 @Override
130 public int countMedia(SpecimenOrObservationBase occurence) {
131 checkNotInPriorView("OccurrenceDaoHibernateImpl.countMedia(SpecimenOrObservationBase occurence)");
132 Query query = getSession().createQuery("select count(media) from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");
133 query.setParameter("occurence", occurence);
134
135 return ((Long)query.uniqueResult()).intValue();
136 }
137
138 /* (non-Javadoc)
139 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDerivationEvents(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List)
140 */
141 @Override
142 public List<DerivationEvent> getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber, List<String> propertyPaths) {
143 checkNotInPriorView("OccurrenceDaoHibernateImpl.getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber)");
144 Query query = getSession().createQuery("select distinct derivationEvent from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
145 query.setParameter("occurence", occurence);
146
147 if(pageSize != null) {
148 query.setMaxResults(pageSize);
149 if(pageNumber != null) {
150 query.setFirstResult(pageNumber * pageSize);
151 } else {
152 query.setFirstResult(0);
153 }
154 }
155
156 List<DerivationEvent> result = query.list();
157 defaultBeanInitializer.initializeAll(result, propertyPaths);
158 return result;
159 }
160
161 /* (non-Javadoc)
162 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)
163 */
164 @Override
165 public List<DeterminationEvent> getDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
166 AuditEvent auditEvent = getAuditEventFromContext();
167 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
168 Criteria criteria = getSession().createCriteria(DeterminationEvent.class);
169 if(occurrence != null) {
170 criteria.add(Restrictions.eq("identifiedUnit",occurrence));
171 }
172
173 if(taxonBase != null) {
174 criteria.add(Restrictions.eq("taxon",taxonBase));
175 }
176
177 if(pageSize != null) {
178 criteria.setMaxResults(pageSize);
179 if(pageNumber != null) {
180 criteria.setFirstResult(pageNumber * pageSize);
181 } else {
182 criteria.setFirstResult(0);
183 }
184 }
185 List<DeterminationEvent> result = criteria.list();
186 defaultBeanInitializer.initializeAll(result, propertyPaths);
187 return result;
188 } else {
189 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());
190 if(occurrence != null) {
191 query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));
192 }
193
194 if(taxonBase != null) {
195 query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));
196 }
197 if(pageSize != null) {
198 query.setMaxResults(pageSize);
199 if(pageNumber != null) {
200 query.setFirstResult(pageNumber * pageSize);
201 } else {
202 query.setFirstResult(0);
203 }
204 }
205 List<DeterminationEvent> result = query.getResultList();
206 defaultBeanInitializer.initializeAll(result, propertyPaths);
207 return result;
208 }
209 }
210
211 /* (non-Javadoc)
212 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getMedia(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List)
213 */
214 @Override
215 public List<Media> getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
216 checkNotInPriorView("OccurrenceDaoHibernateImpl.getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths)");
217 Query query = getSession().createQuery("select media from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");
218 query.setParameter("occurence", occurence);
219
220 if(pageSize != null) {
221 query.setMaxResults(pageSize);
222 if(pageNumber != null) {
223 query.setFirstResult(pageNumber * pageSize);
224 } else {
225 query.setFirstResult(0);
226 }
227 }
228
229 List<Media> results = query.list();
230 defaultBeanInitializer.initializeAll(results, propertyPaths);
231 return results;
232 }
233
234 /* (non-Javadoc)
235 * @see eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase#rebuildIndex()
236 */
237 @Override
238 public void rebuildIndex() {
239 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
240
241 for(SpecimenOrObservationBase occurrence : list(null,null)) { // re-index all taxon base
242
243 for(DeterminationEvent determination : (Set<DeterminationEvent>)occurrence.getDeterminations()) {
244 Hibernate.initialize(determination.getActor());
245 Hibernate.initialize(determination.getTaxon());
246 }
247 Hibernate.initialize(occurrence.getDefinition());
248 if(occurrence instanceof DerivedUnit) {
249 DerivedUnit derivedUnit = (DerivedUnit) occurrence;
250 Hibernate.initialize(derivedUnit.getCollection());
251 if(derivedUnit.getCollection() != null) {
252 Hibernate.initialize(derivedUnit.getCollection().getSuperCollection());
253 Hibernate.initialize(derivedUnit.getCollection().getInstitute());
254 }
255 Hibernate.initialize(derivedUnit.getStoredUnder());
256 SpecimenOrObservationBase original = derivedUnit.getOriginalUnit();
257 if(original != null && original.isInstanceOf(FieldUnit.class)) {
258 FieldUnit fieldUnit = original.deproxy(original, FieldUnit.class);
259 Hibernate.initialize(fieldUnit.getGatheringEvent());
260 if(fieldUnit.getGatheringEvent() != null) {
261 Hibernate.initialize(fieldUnit.getGatheringEvent().getActor());
262 }
263 }
264 }
265 fullTextSession.index(occurrence);
266 }
267 fullTextSession.flushToIndexes();
268 }
269
270 /* (non-Javadoc)
271 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#count(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase)
272 */
273 @Override
274 public int count(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs) {
275
276 Criteria criteria = null;
277 if(clazz == null) {
278 criteria = getSession().createCriteria(type);
279 } else {
280 criteria = getSession().createCriteria(clazz);
281 }
282
283 criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));
284 criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
285 return ((Number)criteria.uniqueResult()).intValue();
286 }
287
288 /* (non-Javadoc)
289 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#list(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
290 */
291 @Override
292 public List<SpecimenOrObservationBase> list(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
293 Criteria criteria = null;
294 if(clazz == null) {
295 criteria = getSession().createCriteria(type);
296 } else {
297 criteria = getSession().createCriteria(clazz);
298 }
299
300 criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));
301
302 if(limit != null) {
303 if(start != null) {
304 criteria.setFirstResult(start);
305 } else {
306 criteria.setFirstResult(0);
307 }
308 criteria.setMaxResults(limit);
309 }
310
311 addOrder(criteria,orderHints);
312
313 List<SpecimenOrObservationBase> results = criteria.list();
314 defaultBeanInitializer.initializeAll(results, propertyPaths);
315 return results;
316 }
317
318 /* (non-Javadoc)
319 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDerivedUnitUuidAndTitleCache()
320 */
321 @Override
322 public List<UuidAndTitleCache<DerivedUnit>> getDerivedUnitUuidAndTitleCache() {
323 List<UuidAndTitleCache<DerivedUnit>> list = new ArrayList<UuidAndTitleCache<DerivedUnit>>();
324 Session session = getSession();
325
326 Query query = session.createQuery("select uuid, titleCache from " + type.getSimpleName() + " where NOT dtype = " + FieldUnit.class.getSimpleName());
327
328 List<Object[]> result = query.list();
329
330 for(Object[] object : result){
331 list.add(new UuidAndTitleCache<DerivedUnit>(DerivedUnit.class, (UUID) object[0], (String) object[1]));
332 }
333
334 return list;
335 }
336
337 /* (non-Javadoc)
338 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getFieldUnitUuidAndTitleCache()
339 */
340 @Override
341 public List<UuidAndTitleCache<FieldUnit>> getFieldUnitUuidAndTitleCache() {
342 List<UuidAndTitleCache<FieldUnit>> list = new ArrayList<UuidAndTitleCache<FieldUnit>>();
343 Session session = getSession();
344
345 Query query = session.createQuery("select uuid, titleCache from " + type.getSimpleName() + " where dtype = " + FieldUnit.class.getSimpleName());
346
347 List<Object[]> result = query.list();
348
349 for(Object[] object : result){
350 list.add(new UuidAndTitleCache<FieldUnit>(FieldUnit.class, (UUID) object[0], (String) object[1]));
351 }
352
353 return list;
354 }
355
356 /* (non-Javadoc)
357 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#listByAnyAssociation(java.lang.Class, eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)
358 */
359 @Override
360 public <T extends SpecimenOrObservationBase> List<T> listByAssociatedTaxon(Class<T> type,
361 Taxon associatedTaxon, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
362
363 Set<SpecimenOrObservationBase> setOfAll = new HashSet<SpecimenOrObservationBase>();
364
365 // A Taxon may be referenced by the DeterminationEvent of the SpecimenOrObservationBase
366 List<SpecimenOrObservationBase> byDetermination = list(type, associatedTaxon, null, 0, null, null);
367 setOfAll.addAll(byDetermination);
368
369 // The IndividualsAssociation elements in a TaxonDescription contain DerivedUnits
370 List<IndividualsAssociation> byIndividualsAssociation = descriptionDao.getDescriptionElementForTaxon(
371 associatedTaxon.getUuid(), null, IndividualsAssociation.class, null, 0, null);
372 for(IndividualsAssociation individualsAssociation : byIndividualsAssociation){
373 setOfAll.add(individualsAssociation.getAssociatedSpecimenOrObservation());
374 }
375
376 // SpecimenTypeDesignations may be associated with the TaxonName.
377 List<SpecimenTypeDesignation> bySpecimenTypeDesignation = taxonNameDao.getTypeDesignations(associatedTaxon.getName(),
378 SpecimenTypeDesignation.class, null, null, 0, null);
379 for (SpecimenTypeDesignation specimenTypeDesignation : bySpecimenTypeDesignation) {
380 setOfAll.add(specimenTypeDesignation.getTypeSpecimen());
381 }
382
383 // SpecimenTypeDesignations may be associated with any HomotypicalGroup related to the specific Taxon.
384 for(HomotypicalGroup homotypicalGroup : associatedTaxon.getHomotypicSynonymyGroups()) {
385 List<SpecimenTypeDesignation> byHomotypicalGroup = homotypicalGroupDao.getTypeDesignations(homotypicalGroup, SpecimenTypeDesignation.class, null, null, 0, null);
386 for (SpecimenTypeDesignation specimenTypeDesignation : byHomotypicalGroup) {
387 setOfAll.add(specimenTypeDesignation.getTypeSpecimen());
388 }
389 }
390
391 if(setOfAll.size() == 0){
392 // no need querying the data base
393 return new ArrayList<T>();
394 }
395
396 String queryString =
397 "select sob " +
398 " from SpecimenOrObservationBase sob" +
399 " where sob in (:setOfAll)";
400
401 if(type != null){
402 queryString += " and sob.class = :type";
403 }
404
405 if(orderHints != null && orderHints.size() > 0){
406 queryString += " order by ";
407 String orderStr = "";
408 for(OrderHint orderHint : orderHints){
409 if(orderStr.length() > 0){
410 orderStr += ", ";
411 }
412 queryString += "sob." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
413 }
414 queryString += orderStr;
415 }
416
417 Query query = getSession().createQuery(queryString);
418 query.setParameterList("setOfAll", setOfAll);
419
420 if(type != null){
421 query.setParameter("type", type.getSimpleName());
422 }
423
424 if(limit != null) {
425 if(start != null) {
426 query.setFirstResult(start);
427 } else {
428 query.setFirstResult(0);
429 }
430 query.setMaxResults(limit);
431 }
432
433
434 List<T> results = query.list();
435 defaultBeanInitializer.initializeAll(results, propertyPaths);
436 return results;
437 }
438
439 @Override
440 public Collection<SpecimenTypeDesignation> listTypeDesignations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
441 String queryString = "FROM SpecimenTypeDesignation designations WHERE designations.typeSpecimen = :specimen";
442
443 if(orderHints != null && orderHints.size() > 0){
444 queryString += " order by ";
445 String orderStr = "";
446 for(OrderHint orderHint : orderHints){
447 if(orderStr.length() > 0){
448 orderStr += ", ";
449 }
450 queryString += "designations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
451 }
452 queryString += orderStr;
453 }
454
455 Query query = getSession().createQuery(queryString);
456 query.setParameter("specimen", specimen);
457
458 if(limit != null) {
459 if(start != null) {
460 query.setFirstResult(start);
461 } else {
462 query.setFirstResult(0);
463 }
464 query.setMaxResults(limit);
465 }
466
467 List results = query.list();
468 defaultBeanInitializer.initializeAll(results, propertyPaths);
469 return results;
470 }
471
472 /* (non-Javadoc)
473 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
474 */
475 @Override
476 public Collection<IndividualsAssociation> listIndividualsAssociations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
477 //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
478 String queryString = "FROM IndividualsAssociation associations WHERE associations.associatedSpecimenOrObservation = :specimen";
479
480 if(orderHints != null && orderHints.size() > 0){
481 queryString += " order by ";
482 String orderStr = "";
483 for(OrderHint orderHint : orderHints){
484 if(orderStr.length() > 0){
485 orderStr += ", ";
486 }
487 queryString += "associations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
488 }
489 queryString += orderStr;
490 }
491
492 Query query = getSession().createQuery(queryString);
493 query.setParameter("specimen", specimen);
494
495 if(limit != null) {
496 if(start != null) {
497 query.setFirstResult(start);
498 } else {
499 query.setFirstResult(0);
500 }
501 query.setMaxResults(limit);
502 }
503
504 List results = query.list();
505 defaultBeanInitializer.initializeAll(results, propertyPaths);
506 return results;
507 }
508
509 /* (non-Javadoc)
510 * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#listAssociatedTaxa(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)
511 */
512 @Override
513 public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
514 //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
515 String queryString = "FROM DescriptionBase descriptions WHERE descriptions.describedSpecimenOrObservation = :specimen";
516
517 if(orderHints != null && orderHints.size() > 0){
518 queryString += " order by ";
519 String orderStr = "";
520 for(OrderHint orderHint : orderHints){
521 if(orderStr.length() > 0){
522 orderStr += ", ";
523 }
524 queryString += "descriptions." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
525 }
526 queryString += orderStr;
527 }
528
529 Query query = getSession().createQuery(queryString);
530 query.setParameter("specimen", specimen);
531
532 if(limit != null) {
533 if(start != null) {
534 query.setFirstResult(start);
535 } else {
536 query.setFirstResult(0);
537 }
538 query.setMaxResults(limit);
539 }
540
541 List results = query.list();
542 defaultBeanInitializer.initializeAll(results, propertyPaths);
543 return results;
544 }
545
546 }