Merged from trunk to statistics branch
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / description / DescriptionDaoImpl.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.persistence.dao.hibernate.description;
11
12 import java.util.ArrayList;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.UUID;
17
18 import org.apache.log4j.Logger;
19 import org.hibernate.Criteria;
20 import org.hibernate.Query;
21 import org.hibernate.criterion.ProjectionList;
22 import org.hibernate.criterion.Projections;
23 import org.hibernate.criterion.Restrictions;
24 import org.hibernate.envers.query.AuditEntity;
25 import org.hibernate.envers.query.AuditQuery;
26 import org.springframework.beans.factory.annotation.Qualifier;
27 import org.springframework.stereotype.Repository;
28
29 import eu.etaxonomy.cdm.model.common.DefinedTerm;
30 import eu.etaxonomy.cdm.model.common.LSID;
31 import eu.etaxonomy.cdm.model.common.MarkerType;
32 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
33 import eu.etaxonomy.cdm.model.description.DescriptionBase;
34 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
35 import eu.etaxonomy.cdm.model.description.Feature;
36 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
37 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
38 import eu.etaxonomy.cdm.model.description.TaxonDescription;
39 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
40 import eu.etaxonomy.cdm.model.location.NamedArea;
41 import eu.etaxonomy.cdm.model.media.Media;
42 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43 import eu.etaxonomy.cdm.model.taxon.Taxon;
44 import eu.etaxonomy.cdm.model.view.AuditEvent;
45 import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException;
46 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
47 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
48 import eu.etaxonomy.cdm.persistence.query.MatchMode;
49 import eu.etaxonomy.cdm.persistence.query.OrderHint;
50
51 @Repository
52 @Qualifier("descriptionDaoImpl")
53 public class DescriptionDaoImpl extends IdentifiableDaoBase<DescriptionBase> implements IDescriptionDao{
54
55 private static final Logger logger = Logger.getLogger(DescriptionDaoImpl.class);
56
57 public DescriptionDaoImpl() {
58 super(DescriptionBase.class);
59 indexedClasses = new Class[3];
60 indexedClasses[0] = TaxonDescription.class;
61 indexedClasses[1] = TaxonNameDescription.class;
62 indexedClasses[2] = SpecimenDescription.class;
63 }
64
65 // @Override //Override for testing
66 // public DescriptionBase load(UUID uuid, List<String> propertyPaths){
67 // DescriptionBase bean = findByUuid(uuid);
68 // if(bean == null){
69 // return bean;
70 // }
71 // defaultBeanInitializer.initialize(bean, propertyPaths);
72 //
73 // return bean;
74 // }
75
76 @Override
77 public int countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status) {
78 checkNotInPriorView("DescriptionDaoImpl.countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status)");
79 Query query = null;
80
81 if(status == null) {
82 query = getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.descriptionElements element join element.area area where area in (:namedAreas)");
83 } else {
84 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");
85 query.setParameter("status", status);
86 }
87 query.setParameterList("namedAreas", namedAreas);
88
89 return ((Long)query.uniqueResult()).intValue();
90 }
91
92 @Override
93 public int countDescriptionElements(DescriptionBase description, Set<Feature> features, Class<? extends DescriptionElementBase> clazz) {
94 return countDescriptionElements(description, null, features, clazz);
95 }
96
97 @Override
98 public int countDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
99 Set<Feature> features, Class<? extends DescriptionElementBase> clazz) {
100 AuditEvent auditEvent = getAuditEventFromContext();
101 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
102 Criteria criteria = null;
103 if(clazz == null) {
104 criteria = getSession().createCriteria(DescriptionElementBase.class);
105 } else {
106 criteria = getSession().createCriteria(clazz);
107 }
108
109 if(description != null) {
110 criteria.add(Restrictions.eq("inDescription", description));
111 }
112
113 if(descriptionType != null) {
114 criteria.createAlias("inDescription", "d").add(Restrictions.eq("d.class", descriptionType));
115 }
116
117 if(features != null && !features.isEmpty()) {
118 criteria.add(Restrictions.in("feature", features));
119 }
120
121 criteria.setProjection(Projections.rowCount());
122
123 return ((Number)criteria.uniqueResult()).intValue();
124 } else {
125 if(features != null && !features.isEmpty()) {
126 Integer count = 0;
127 for(Feature f : features) {
128 AuditQuery query = null;
129 if(clazz == null) {
130 query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
131 } else {
132 query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
133 }
134
135 if(description != null) {
136 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
137 }
138
139 if(descriptionType != null) {
140 query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
141 }
142
143 query.add(AuditEntity.relatedId("feature").eq(f.getId()));
144 query.addProjection(AuditEntity.id().count("id"));
145 count += ((Long)query.getSingleResult()).intValue();
146 }
147
148 return count;
149 } else {
150 AuditQuery query = null;
151 if(clazz == null) {
152 query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
153 } else {
154 query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
155 }
156
157 if(description != null) {
158 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
159 }
160 if(descriptionType != null) {
161 query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
162 }
163
164 query.addProjection(AuditEntity.id().count("id"));
165 return ((Long)query.getSingleResult()).intValue();
166 }
167 }
168 }
169
170 @Override
171 public int countDescriptions(Class<? extends DescriptionBase> clazz, Boolean hasImages, Boolean hasText, Set<Feature> features) {
172 checkNotInPriorView("DescriptionDaoImpl.countDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features)");
173 Criteria inner = null;
174
175 if(clazz == null) {
176 inner = getSession().createCriteria(type);
177 } else {
178 inner = getSession().createCriteria(clazz);
179 }
180
181 Criteria elementsCriteria = inner.createCriteria("descriptionElements");
182 if(hasText != null) {
183 if(hasText) {
184 elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
185 } else {
186 elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
187 }
188 }
189
190 if(hasImages != null) {
191 if(hasImages) {
192 elementsCriteria.add(Restrictions.isNotEmpty("media"));
193 } else {
194 elementsCriteria.add(Restrictions.isEmpty("media"));
195 }
196 }
197
198 if(features != null && !features.isEmpty()) {
199 elementsCriteria.add(Restrictions.in("feature", features));
200 }
201
202 inner.setProjection(Projections.countDistinct("id"));
203
204 return ((Number) inner.uniqueResult()).intValue();
205 }
206
207 @Override
208 public int countTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes,Set<NamedArea> geographicalScopes, Set<MarkerType> markerTypes) {
209 AuditEvent auditEvent = getAuditEventFromContext();
210 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
211 Criteria criteria = getSession().createCriteria(TaxonDescription.class);
212
213 if(taxon != null) {
214 criteria.add(Restrictions.eq("taxon", taxon));
215 }
216
217 if(scopes != null && !scopes.isEmpty()) {
218 Set<Integer> scopeIds = new HashSet<Integer>();
219 for(DefinedTerm s : scopes) {
220 scopeIds.add(s.getId());
221 }
222 criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
223 }
224
225 if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
226 Set<Integer> geoScopeIds = new HashSet<Integer>();
227 for(NamedArea n : geographicalScopes) {
228 geoScopeIds.add(n.getId());
229 }
230 criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
231 }
232
233
234 addMarkerTypesCriterion(markerTypes, criteria);
235
236
237 criteria.setProjection(Projections.rowCount());
238
239 return ((Number)criteria.uniqueResult()).intValue();
240 } else {
241 if((scopes == null || scopes.isEmpty())&& (geographicalScopes == null || geographicalScopes.isEmpty()) && (markerTypes == null || markerTypes.isEmpty())) {
242 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonDescription.class,auditEvent.getRevisionNumber());
243 if(taxon != null) {
244 query.add(AuditEntity.relatedId("taxon").eq(taxon.getId()));
245 }
246
247 query.addProjection(AuditEntity.id().count("id"));
248
249 return ((Long)query.getSingleResult()).intValue();
250 } else {
251 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
252 }
253 }
254 }
255
256 /**
257 * @param markerTypes
258 * @param criteria
259 *
260 */
261 //TODO move to AnnotatableEntityDao(?)
262 private void addMarkerTypesCriterion(Set<MarkerType> markerTypes, Criteria criteria) {
263
264 if(markerTypes != null && !markerTypes.isEmpty()) {
265 Set<Integer> markerTypeIds = new HashSet<Integer>();
266 for(MarkerType markerType : markerTypes) {
267 markerTypeIds.add(markerType.getId());
268 }
269 criteria.createCriteria("markers").add(Restrictions.eq("flag", true))
270 .createAlias("markerType", "mt")
271 .add(Restrictions.in("mt.id", markerTypeIds));
272 } else if (markerTypes != null && markerTypes.isEmpty()){
273 //AT: added in case the projects requires an third state description, An empty Marker type set
274 }
275 }
276 @Override
277 public List<DescriptionElementBase> getDescriptionElements(
278 DescriptionBase description, Set<Feature> features,
279 Class<? extends DescriptionElementBase> clazz, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
280 return getDescriptionElements(description, null, features, clazz, pageSize, pageNumber, propertyPaths);
281 }
282
283 @Override
284 public List<DescriptionElementBase> getDescriptionElements(
285 DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
286 Set<Feature> features,
287 Class<? extends DescriptionElementBase> clazz,
288 Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
289
290 AuditEvent auditEvent = getAuditEventFromContext();
291 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
292 Criteria criteria = null;
293 if(clazz == null) {
294 criteria = getSession().createCriteria(DescriptionElementBase.class);
295 } else {
296 criteria = getSession().createCriteria(clazz);
297 }
298
299 if(description != null) {
300 criteria.add(Restrictions.eq("inDescription", description));
301 }
302 if(descriptionType != null) {
303 criteria.createAlias("inDescription", "d").add(Restrictions.eq("d.class", descriptionType));
304 }
305
306 if(features != null && !features.isEmpty()) {
307 criteria.add(Restrictions.in("feature", features));
308 }
309
310 if(pageSize != null) {
311 criteria.setMaxResults(pageSize);
312 if(pageNumber != null) {
313 criteria.setFirstResult(pageNumber * pageSize);
314 }
315 }
316
317 List<DescriptionElementBase> results = criteria.list();
318
319 defaultBeanInitializer.initializeAll(results, propertyPaths);
320
321 return results;
322 } else {
323 List<DescriptionElementBase> result = new ArrayList<DescriptionElementBase>();
324 if(features != null && !features.isEmpty()) {
325
326 for(Feature f : features) {
327 AuditQuery query = null;
328 if(clazz == null) {
329 query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
330 } else {
331 query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
332 }
333
334 if(description != null) {
335 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
336 }
337
338 if(descriptionType != null) {
339 query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
340 }
341
342 query.add(AuditEntity.relatedId("feature").eq(f.getId()));
343 result.addAll(query.getResultList());
344 }
345 } else {
346 AuditQuery query = null;
347 if(clazz == null) {
348 query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
349 } else {
350 query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
351 }
352
353 if(description != null) {
354 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
355 }
356
357 if(descriptionType != null) {
358 query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
359 }
360
361 result = query.getResultList();
362 }
363
364 defaultBeanInitializer.initializeAll(result, propertyPaths);
365
366 return result;
367 }
368 }
369
370 @Override
371 public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScopes, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
372 AuditEvent auditEvent = getAuditEventFromContext();
373 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
374 Criteria criteria = getSession().createCriteria(TaxonDescription.class);
375
376 if(taxon != null) {
377 criteria.add(Restrictions.eq("taxon", taxon));
378 }
379
380 if(scopes != null && !scopes.isEmpty()) {
381 Set<Integer> scopeIds = new HashSet<Integer>();
382 for(DefinedTerm s : scopes) {
383 scopeIds.add(s.getId());
384 }
385 criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
386 }
387
388 if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
389 Set<Integer> geoScopeIds = new HashSet<Integer>();
390 for(NamedArea n : geographicalScopes) {
391 geoScopeIds.add(n.getId());
392 }
393 criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
394 }
395
396 addMarkerTypesCriterion(markerTypes, criteria);
397
398 if(pageSize != null) {
399 criteria.setMaxResults(pageSize);
400 if(pageNumber != null) {
401 criteria.setFirstResult(pageNumber * pageSize);
402 }
403 }
404
405 List<TaxonDescription> results = criteria.list();
406
407 defaultBeanInitializer.initializeAll(results, propertyPaths);
408
409 return results;
410 } else {
411 if((scopes == null || scopes.isEmpty())&& (geographicalScopes == null || geographicalScopes.isEmpty())&& (markerTypes == null || markerTypes.isEmpty())) {
412 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonDescription.class,auditEvent.getRevisionNumber());
413 if(taxon != null) {
414 query.add(AuditEntity.relatedId("taxon").eq(taxon.getId()));
415 }
416
417 if(pageSize != null) {
418 query.setMaxResults(pageSize);
419 if(pageNumber != null) {
420 query.setFirstResult(pageNumber * pageSize);
421 } else {
422 query.setFirstResult(0);
423 }
424 }
425
426 List<TaxonDescription> results = query.getResultList();
427 defaultBeanInitializer.initializeAll(results, propertyPaths);
428 return results;
429 } else {
430 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
431 }
432 }
433 }
434
435 @Override
436 public List<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
437 AuditEvent auditEvent = getAuditEventFromContext();
438 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
439 Criteria criteria = getSession().createCriteria(TaxonNameDescription.class);
440
441 if(name != null) {
442 criteria.add(Restrictions.eq("taxonName", name));
443 }
444
445 if(pageSize != null) {
446 criteria.setMaxResults(pageSize);
447 if(pageNumber != null) {
448 criteria.setFirstResult(pageNumber * pageSize);
449 }
450 }
451
452 List<TaxonNameDescription> results = criteria.list();
453
454 defaultBeanInitializer.initializeAll(results, propertyPaths);
455
456 return results;
457 } else {
458 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription.class,auditEvent.getRevisionNumber());
459
460 if(name != null) {
461 query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
462 }
463
464 if(pageSize != null) {
465 query.setMaxResults(pageSize);
466 if(pageNumber != null) {
467 query.setFirstResult(pageNumber * pageSize);
468 }
469 }
470
471 List<TaxonNameDescription> results = query.getResultList();
472
473 defaultBeanInitializer.initializeAll(results, propertyPaths);
474
475 return results;
476 }
477
478 }
479
480 @Override
481 public int countTaxonNameDescriptions(TaxonNameBase name) {
482 AuditEvent auditEvent = getAuditEventFromContext();
483 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
484 Criteria criteria = getSession().createCriteria(TaxonNameDescription.class);
485
486 if(name != null) {
487 criteria.add(Restrictions.eq("taxonName", name));
488 }
489
490 criteria.setProjection(Projections.rowCount());
491
492 return ((Number)criteria.uniqueResult()).intValue();
493 } else {
494 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription.class,auditEvent.getRevisionNumber());
495
496 if(name != null) {
497 query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
498 }
499
500 query.addProjection(AuditEntity.id().count("id"));
501 return ((Long)query.getSingleResult()).intValue();
502 }
503 }
504
505 /**
506 * Should use a DetachedCriteria & subquery, but HHH-158 prevents this, for now.
507 *
508 * e.g. DetachedCriteria inner = DestachedCriteria.forClass(type);
509 *
510 * outer.add(Subqueries.propertyIn("id", inner));
511 */
512 @Override
513 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) {
514 checkNotInPriorView("DescriptionDaoImpl.listDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features, Integer pageSize, Integer pageNumber)");
515 Criteria inner = null;
516
517 if(clazz == null) {
518 inner = getSession().createCriteria(type);
519 } else {
520 inner = getSession().createCriteria(clazz);
521 }
522
523 Criteria elementsCriteria = inner.createCriteria("descriptionElements");
524 if(hasText != null) {
525 if(hasText) {
526 elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
527 } else {
528 elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
529 }
530 }
531
532 if(hasImages != null) {
533 if(hasImages) {
534 elementsCriteria.add(Restrictions.isNotEmpty("media"));
535 } else {
536 elementsCriteria.add(Restrictions.isEmpty("media"));
537 }
538 }
539
540 if(features != null && !features.isEmpty()) {
541 elementsCriteria.add(Restrictions.in("feature", features));
542 }
543
544 inner.setProjection(Projections.distinct(Projections.id()));
545
546 List<Object> intermediateResult = inner.list();
547
548 if(intermediateResult.isEmpty()) {
549 return new ArrayList<DescriptionBase>();
550 }
551
552 Integer[] resultIds = new Integer[intermediateResult.size()];
553 for(int i = 0; i < resultIds.length; i++) {
554 resultIds[i] = ((Number)intermediateResult.get(i)).intValue();
555 }
556
557 Criteria outer = null;
558
559 if(clazz == null) {
560 outer = getSession().createCriteria(type);
561 } else {
562 outer = getSession().createCriteria(clazz);
563 }
564
565 outer.add(Restrictions.in("id", resultIds));
566 addOrder(outer, orderHints);
567
568 if(pageSize != null) {
569 outer.setMaxResults(pageSize);
570 if(pageNumber != null) {
571 outer.setFirstResult(pageNumber * pageSize);
572 }
573 }
574
575 List<DescriptionBase> results = outer.list();
576 defaultBeanInitializer.initializeAll(results, propertyPaths);
577 return results;
578 }
579
580 @Override
581 public List<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
582 checkNotInPriorView("DescriptionDaoImpl.searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
583
584 Criteria criteria = getSession().createCriteria(TaxonDescription.class);
585 Criteria elements = criteria.createCriteria("descriptionElements", "descriptionElement", Criteria.LEFT_JOIN);
586 elements.add(Restrictions.in("area", namedAreas.toArray()));
587
588 if(status != null) {
589 elements.add(Restrictions.eq("status", status));
590 }
591
592 ProjectionList projectionList = Projections.projectionList().add(Projections.id());
593
594 if(orderHints != null && !orderHints.isEmpty()) {
595 for(OrderHint orderHint : orderHints) {
596 projectionList = projectionList.add(Projections.property(orderHint.getPropertyName()));
597 }
598 }
599
600 criteria.setProjection(Projections.distinct(projectionList));
601
602 if(pageSize != null) {
603 criteria.setMaxResults(pageSize);
604 if(pageNumber != null) {
605 criteria.setFirstResult(pageNumber * pageSize);
606 }
607 }
608
609 addOrder(criteria,orderHints);
610
611 List<Object> intermediateResult = criteria.list();
612
613 if(intermediateResult.isEmpty()) {
614 return new ArrayList<TaxonDescription>();
615 }
616
617 Integer[] resultIds = new Integer[intermediateResult.size()];
618 for(int i = 0; i < resultIds.length; i++) {
619 if(orderHints == null || orderHints.isEmpty()) {
620 resultIds[i] = ((Number)intermediateResult.get(i)).intValue();
621 } else {
622 resultIds[i] = ((Number)((Object[])intermediateResult.get(i))[0]).intValue();
623 }
624 }
625
626 criteria = getSession().createCriteria(TaxonDescription.class);
627 criteria.add(Restrictions.in("id", resultIds));
628 addOrder(criteria,orderHints);
629
630 List<TaxonDescription> results = criteria.list();
631 defaultBeanInitializer.initializeAll(results, propertyPaths);
632 return results;
633 }
634
635 @Override
636 public List<CommonTaxonName> searchDescriptionByCommonName(String queryString, MatchMode matchMode, Integer pageSize, Integer pageNumber) {
637
638 Criteria crit = getSession().createCriteria(CommonTaxonName.class);
639 if (matchMode == MatchMode.EXACT) {
640 crit.add(Restrictions.eq("name", matchMode.queryStringFrom(queryString)));
641 } else {
642 crit.add(Restrictions.ilike("name", matchMode.queryStringFrom(queryString)));
643 }
644
645 if(pageSize != null) {
646 crit.setMaxResults(pageSize);
647 if(pageNumber != null) {
648 crit.setFirstResult(pageNumber * pageSize);
649 }
650 }
651 List<CommonTaxonName> results = crit.list();
652 return results;
653 }
654
655 @Override
656 public Integer countDescriptionByCommonName(String queryString, MatchMode matchMode) {
657 //TODO inprove performance
658 List<CommonTaxonName> results = searchDescriptionByCommonName(queryString, matchMode, null, null);
659 return results.size();
660 }
661
662 @Override
663 public DescriptionBase find(LSID lsid) {
664 DescriptionBase descriptionBase = super.find(lsid);
665 if(descriptionBase != null) {
666 List<String> propertyPaths = new ArrayList<String>();
667 propertyPaths.add("createdBy");
668 propertyPaths.add("updatedBy");
669 propertyPaths.add("taxon");
670 propertyPaths.add("taxonName");
671 propertyPaths.add("descriptionElements");
672 propertyPaths.add("descriptionElements.createdBy");
673 propertyPaths.add("descriptionElements.updatedBy");
674 propertyPaths.add("descriptionElements.feature");
675 propertyPaths.add("descriptionElements.multilanguageText");
676 propertyPaths.add("descriptionElements.multilanguageText.language");
677 propertyPaths.add("descriptionElements.area");
678 propertyPaths.add("descriptionElements.status");
679 propertyPaths.add("descriptionElements.modifyingText");
680 propertyPaths.add("descriptionElementsmodifyingText.language");
681 propertyPaths.add("descriptionElements.modifiers");
682
683 defaultBeanInitializer.initialize(descriptionBase, propertyPaths);
684 }
685 return descriptionBase;
686 }
687
688
689 @Override
690 public <T extends DescriptionElementBase> List<T> getDescriptionElementForTaxon(
691 Taxon taxon, Set<Feature> features,
692 Class<T> type, Integer pageSize,
693 Integer pageNumber, List<String> propertyPaths) {
694
695 Query query = prepareGetDescriptionElementForTaxon(taxon, features, type, pageSize, pageNumber, false);
696
697 if (logger.isDebugEnabled()){logger.debug(" dao: get list ...");}
698 List<T> results = query.list();
699 if (logger.isDebugEnabled()){logger.debug(" dao: initialize ...");}
700 defaultBeanInitializer.initializeAll(results, propertyPaths);
701 if (logger.isDebugEnabled()){logger.debug(" dao: initialize - DONE");}
702 return results;
703 }
704
705 @Override
706 public <T extends DescriptionElementBase> long countDescriptionElementForTaxon(
707 Taxon taxon, Set<Feature> features, Class<T> type) {
708
709 Query query = prepareGetDescriptionElementForTaxon(taxon, features, type, null, null, true);
710
711 return (Long)query.uniqueResult();
712 }
713
714 /**
715 * @param taxon
716 * @param features
717 * @param type
718 * @param pageSize
719 * @param pageNumber
720 * @return
721 */
722 private <T extends DescriptionElementBase> Query prepareGetDescriptionElementForTaxon(Taxon taxon,
723 Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, boolean asCountQuery) {
724
725 String listOrCount;
726 if(asCountQuery){
727 listOrCount = "count(de)";
728 } else {
729 listOrCount = "de";
730 }
731 String queryString = "select " + listOrCount +
732 " from TaxonDescription as td" +
733 " left join td.descriptionElements as de" +
734 " where td.taxon = :taxon ";
735
736 if(type != null){
737 queryString += " and de.class = :type";
738 }
739 if (features != null && features.size() > 0){
740 queryString += " and de.feature in (:features) ";
741 }
742 // System.out.println(queryString);
743 Query query = getSession().createQuery(queryString);
744
745 query.setParameter("taxon", taxon);
746 if(type != null){
747 query.setParameter("type", type.getSimpleName());
748 }
749 if(features != null && features.size() > 0){
750 query.setParameterList("features", features) ;
751 }
752
753 if(pageSize != null) {
754 query.setMaxResults(pageSize);
755 if(pageNumber != null) {
756 query.setFirstResult(pageNumber * pageSize);
757 }
758 }
759 return query;
760 }
761
762 /* (non-Javadoc)
763 * @see eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao#listTaxonDescriptionMedia(java.util.UUID, java.lang.Boolean, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)
764 */
765 @Override
766 public List<Media> listTaxonDescriptionMedia(UUID taxonUuid,
767 Boolean limitToGalleries, Set<MarkerType> markerTypes,
768 Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
769
770 AuditEvent auditEvent = getAuditEventFromContext();
771 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
772 String queryString = " SELECT media " +
773 getTaxonDescriptionMediaQueryString(
774 taxonUuid, limitToGalleries, markerTypes);
775 queryString +=
776 " GROUP BY media "
777 // " ORDER BY index(media) " //not functional
778 ;
779
780 Query query = getSession().createQuery(queryString);
781
782 setTaxonDescriptionMediaParameters(query, taxonUuid, limitToGalleries, markerTypes);
783
784
785 // addMarkerTypesCriterion(markerTypes, hql);
786
787 if(pageSize != null) {
788 query.setMaxResults(pageSize);
789 if(pageNumber != null) {
790 query.setFirstResult(pageNumber * pageSize);
791 }
792 }
793
794 List<Media> results = query.list();
795
796 defaultBeanInitializer.initializeAll(results, propertyPaths);
797
798 return results;
799 } else {
800 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid, boolean restrictToGalleries)");
801 }
802 }
803
804
805 /* (non-Javadoc)
806 * @see eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao#countTaxonDescriptionMedia(java.util.UUID, java.lang.Boolean, java.util.Set)
807 */
808 @Override
809 public int countTaxonDescriptionMedia(UUID taxonUuid,
810 Boolean limitToGalleries, Set<MarkerType> markerTypes) {
811 AuditEvent auditEvent = getAuditEventFromContext();
812 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
813 String queryString = " SELECT count(DISTINCT media) " +
814 getTaxonDescriptionMediaQueryString(
815 taxonUuid, limitToGalleries, markerTypes);
816
817 Query query = getSession().createQuery(queryString);
818 setTaxonDescriptionMediaParameters(query, taxonUuid, limitToGalleries, markerTypes);
819 return ((Long)query.uniqueResult()).intValue();
820 }else{
821 throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid)");
822 }
823
824 }
825
826 private void setTaxonDescriptionMediaParameters(Query query, UUID taxonUuid, Boolean limitToGalleries, Set<MarkerType> markerTypes) {
827 if(taxonUuid != null){
828 query.setParameter("uuid", taxonUuid);
829 }
830
831 }
832
833 /**
834 * @param taxonUuid
835 * @param restrictToGalleries
836 * @param markerTypes
837 * @return
838 */
839 private String getTaxonDescriptionMediaQueryString(UUID taxonUuid,
840 Boolean restrictToGalleries, Set<MarkerType> markerTypes) {
841 String fromQueryString =
842 " FROM DescriptionElementBase as deb INNER JOIN " +
843 " deb.inDescription as td "
844 + " INNER JOIN td.taxon as t "
845 + " JOIN deb.media as media "
846 + " LEFT JOIN td.markers marker ";
847
848 String whereQueryString = " WHERE (1=1) ";
849 if (taxonUuid != null){
850 whereQueryString += " AND t.uuid = :uuid ";
851 }
852 if (restrictToGalleries){
853 whereQueryString += " AND td.imageGallery is true ";
854 }
855 if (markerTypes != null && !markerTypes.isEmpty()){
856 whereQueryString += " AND (1=0";
857 for (MarkerType markerType : markerTypes){
858 whereQueryString += " OR ( marker.markerType.id = " + markerType.getId() + " AND marker.flag is true)";
859
860 }
861 whereQueryString += ") ";
862 }
863
864 return fromQueryString + whereQueryString;
865
866 }
867
868 /* (non-Javadoc)
869 * @see eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao#listNamedAreasInUse(java.lang.Integer, java.lang.Integer, java.util.List)
870 */
871 @Override
872 public List<NamedArea> listNamedAreasInUse(Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
873
874 String queryString = "select distinct d.area from Distribution as d";
875 Query query = getSession().createQuery(queryString);
876
877 if(pageSize != null) {
878 query.setMaxResults(pageSize);
879 if(pageNumber != null) {
880 query.setFirstResult(pageNumber * pageSize);
881 }
882 }
883
884 List<NamedArea> results = query.list();
885
886 defaultBeanInitializer.initializeAll(results, propertyPaths);
887
888 return results;
889 }
890
891
892
893 }