Committing large number of changes relating to versioning implementation (#108)
[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.ArrayList;
15 import java.util.List;
16 import java.util.Set;
17
18 import org.apache.log4j.Logger;
19 import org.hibernate.Criteria;
20 import org.hibernate.Query;
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.springframework.beans.factory.annotation.Qualifier;
26 import org.springframework.stereotype.Repository;
27
28 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
29 import eu.etaxonomy.cdm.model.description.DescriptionBase;
30 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
31 import eu.etaxonomy.cdm.model.description.Feature;
32 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
33 import eu.etaxonomy.cdm.model.description.Scope;
34 import eu.etaxonomy.cdm.model.description.TaxonDescription;
35 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
36 import eu.etaxonomy.cdm.model.location.NamedArea;
37 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
38 import eu.etaxonomy.cdm.model.taxon.Taxon;
39 import eu.etaxonomy.cdm.model.view.AuditEvent;
40 import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
41 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
42
43
44 @Repository
45 @Qualifier("descriptionDaoImpl")
46 public class DescriptionDaoImpl extends IdentifiableDaoBase<DescriptionBase> implements IDescriptionDao{
47
48 @SuppressWarnings("unused")
49 private static final Logger logger = Logger.getLogger(DescriptionDaoImpl.class);
50
51 public DescriptionDaoImpl() {
52 super(DescriptionBase.class);
53 }
54
55 public int countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status) {
56 checkNotInPriorView("DescriptionDaoImpl.countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status)");
57 Query query = null;
58
59 if(status == null) {
60 query = getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.elements element join element.area area where area in (:namedAreas)");
61 } else {
62 query = getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.elements element join element.area area join element.status status where area in (:namedAreas) and status = :status");
63 query.setParameter("status", status);
64 }
65 query.setParameterList("namedAreas", namedAreas);
66
67 return ((Long)query.uniqueResult()).intValue();
68 }
69
70 public <TYPE extends DescriptionElementBase> int countDescriptionElements(DescriptionBase description, Set<Feature> features, Class<TYPE> type) {
71 AuditEvent auditEvent = getAuditEventFromContext();
72 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
73 Criteria criteria = getSession().createCriteria(type);
74
75 if(description != null) {
76 criteria.add(Restrictions.eq("inDescription", description));
77 }
78
79 if(features != null && !features.isEmpty()) {
80 criteria.add(Restrictions.in("feature", features));
81 }
82
83 criteria.setProjection(Projections.rowCount());
84
85 return (Integer)criteria.uniqueResult();
86 } else {
87 if(features != null && !features.isEmpty()) {
88 Integer count = 0;
89 for(Feature f : features) {
90 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
91
92 if(description != null) {
93 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
94 }
95
96 query.add(AuditEntity.relatedId("feature").eq(f.getId()));
97 query.addProjection(AuditEntity.id().count("id"));
98 count += ((Long)query.getSingleResult()).intValue();
99 }
100
101 return count;
102 } else {
103 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
104
105 if(description != null) {
106 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
107 }
108 query.addProjection(AuditEntity.id().count("id"));
109 return ((Long)query.getSingleResult()).intValue();
110 }
111 }
112 }
113
114 public <TYPE extends DescriptionBase> int countDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features) {
115 checkNotInPriorView("DescriptionDaoImpl.countDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features)");
116 Criteria inner = getSession().createCriteria(type);
117 Criteria elementsCriteria = inner.createCriteria("elements");
118 if(hasText != null) {
119 if(hasText) {
120 elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
121 } else {
122 elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
123 }
124 }
125
126 if(hasImages != null) {
127 if(hasImages) {
128 elementsCriteria.add(Restrictions.isNotEmpty("media"));
129 } else {
130 elementsCriteria.add(Restrictions.isEmpty("media"));
131 }
132 }
133
134 if(features != null && !features.isEmpty()) {
135 elementsCriteria.add(Restrictions.in("feature", features));
136 }
137
138 inner.setProjection(Projections.countDistinct("id"));
139
140 return (Integer) inner.uniqueResult();
141 }
142
143 public int countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes) {
144 checkNotInPriorView("DescriptionDaoImpl.countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
145 Criteria criteria = getSession().createCriteria(TaxonDescription.class);
146
147 if(taxon != null) {
148 criteria.add(Restrictions.eq("taxon", taxon));
149 }
150
151 if(scopes != null && !scopes.isEmpty()) {
152 Set<Integer> scopeIds = new HashSet<Integer>();
153 for(Scope s : scopes) {
154 scopeIds.add(s.getId());
155 }
156 criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
157 }
158
159 if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
160 Set<Integer> geoScopeIds = new HashSet<Integer>();
161 for(NamedArea n : geographicalScopes) {
162 geoScopeIds.add(n.getId());
163 }
164 criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
165 }
166
167 criteria.setProjection(Projections.rowCount());
168
169 return (Integer)criteria.uniqueResult();
170 }
171
172 public <TYPE extends DescriptionElementBase> List<TYPE> getDescriptionElements(DescriptionBase description, Set<Feature> features, Class<TYPE> type, Integer pageSize, Integer pageNumber) {
173 AuditEvent auditEvent = getAuditEventFromContext();
174 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
175 Criteria criteria = getSession().createCriteria(type);
176
177 if(description != null) {
178 criteria.add(Restrictions.eq("inDescription", description));
179 }
180
181 if(features != null && !features.isEmpty()) {
182 criteria.add(Restrictions.in("feature", features));
183 }
184
185 if(pageSize != null) {
186 criteria.setMaxResults(pageSize);
187 if(pageNumber != null) {
188 criteria.setFirstResult(pageNumber * pageSize);
189 }
190 }
191
192 return (List<TYPE>)criteria.list();
193 } else {
194 if(features != null && !features.isEmpty()) {
195 List<TYPE> result = new ArrayList<TYPE>();
196 for(Feature f : features) {
197 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
198
199 if(description != null) {
200 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
201 }
202
203 query.add(AuditEntity.relatedId("feature").eq(f.getId()));
204 result.addAll((List<TYPE>)query.getResultList());
205 }
206
207 return result;
208 } else {
209 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
210
211 if(description != null) {
212 query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
213 }
214
215 return (List<TYPE>)query.getResultList();
216 }
217 }
218 }
219
220 public List<TaxonDescription> getTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScopes,Integer pageSize, Integer pageNumber) {
221 checkNotInPriorView("DescriptionDaoImpl.getTaxonDescriptions(Taxon taxon, Set<Scope> scopes, Set<NamedArea> geographicalScopes,Integer pageSize, Integer pageNumber)");
222 Criteria criteria = getSession().createCriteria(TaxonDescription.class);
223
224 if(taxon != null) {
225 criteria.add(Restrictions.eq("taxon", taxon));
226 }
227
228 if(scopes != null && !scopes.isEmpty()) {
229 Set<Integer> scopeIds = new HashSet<Integer>();
230 for(Scope s : scopes) {
231 scopeIds.add(s.getId());
232 }
233 criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
234 }
235
236 if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
237 Set<Integer> geoScopeIds = new HashSet<Integer>();
238 for(NamedArea n : geographicalScopes) {
239 geoScopeIds.add(n.getId());
240 }
241 criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
242 }
243
244 if(pageSize != null) {
245 criteria.setMaxResults(pageSize);
246 if(pageNumber != null) {
247 criteria.setFirstResult(pageNumber * pageSize);
248 }
249 }
250
251 return (List<TaxonDescription>)criteria.list();
252 }
253
254 public List<TaxonNameDescription> getTaxonNameDescriptions(TaxonNameBase name, Integer pageSize, Integer pageNumber) {
255 AuditEvent auditEvent = getAuditEventFromContext();
256 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
257 Criteria criteria = getSession().createCriteria(TaxonNameDescription.class);
258
259 if(name != null) {
260 criteria.add(Restrictions.eq("taxonName", name));
261 }
262
263 if(pageSize != null) {
264 criteria.setMaxResults(pageSize);
265 if(pageNumber != null) {
266 criteria.setFirstResult(pageNumber * pageSize);
267 }
268 }
269
270 return (List<TaxonNameDescription>)criteria.list();
271 } else {
272 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription.class,auditEvent.getRevisionNumber());
273
274 if(name != null) {
275 query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
276 }
277
278 if(pageSize != null) {
279 query.setMaxResults(pageSize);
280 if(pageNumber != null) {
281 query.setFirstResult(pageNumber * pageSize);
282 }
283 }
284 return (List<TaxonNameDescription>)query.getResultList();
285 }
286
287 }
288
289 public int countTaxonNameDescriptions(TaxonNameBase name) {
290 AuditEvent auditEvent = getAuditEventFromContext();
291 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
292 Criteria criteria = getSession().createCriteria(TaxonNameDescription.class);
293
294 if(name != null) {
295 criteria.add(Restrictions.eq("taxonName", name));
296 }
297
298 criteria.setProjection(Projections.rowCount());
299
300 return (Integer)criteria.uniqueResult();
301 } else {
302 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription.class,auditEvent.getRevisionNumber());
303
304 if(name != null) {
305 query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
306 }
307
308 query.addProjection(AuditEntity.id().count("id"));
309 return ((Long)query.getSingleResult()).intValue();
310 }
311 }
312
313 /**
314 * Should use a DetachedCriteria & subquery, but HHH-158 prevents this, for now.
315 *
316 * e.g. DetachedCriteria inner = DestachedCriteria.forClass(type);
317 *
318 * outer.add(Subqueries.propertyIn("id", inner));
319 */
320 public <TYPE extends DescriptionBase> List<TYPE> listDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features, Integer pageSize, Integer pageNumber) {
321 checkNotInPriorView("DescriptionDaoImpl.listDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features, Integer pageSize, Integer pageNumber)");
322 Criteria inner = getSession().createCriteria(type);
323 Criteria elementsCriteria = inner.createCriteria("elements");
324 if(hasText != null) {
325 if(hasText) {
326 elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
327 } else {
328 elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
329 }
330 }
331
332 if(hasImages != null) {
333 if(hasImages) {
334 elementsCriteria.add(Restrictions.isNotEmpty("media"));
335 } else {
336 elementsCriteria.add(Restrictions.isEmpty("media"));
337 }
338 }
339
340 if(features != null && !features.isEmpty()) {
341 elementsCriteria.add(Restrictions.in("feature", features));
342 }
343
344 inner.setProjection(Projections.distinct(Projections.id()));
345
346 List<Integer> ids = (List<Integer>)inner.list();
347
348 if(ids.isEmpty()) {
349 return new ArrayList<TYPE>();
350 }
351
352 Criteria outer = getSession().createCriteria(type);
353 outer.add(Restrictions.in("id", ids));
354
355 if(pageSize != null) {
356 outer.setMaxResults(pageSize);
357 if(pageNumber != null) {
358 outer.setFirstResult(pageNumber * pageSize);
359 }
360 }
361
362 return (List<TYPE>)outer.list();
363 }
364
365 public List<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber) {
366 checkNotInPriorView("DescriptionDaoImpl.searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber)");
367 Query query = null;
368
369 if(status == null) {
370 query = getSession().createQuery("select distinct description from TaxonDescription description left join description.elements element join element.area area where area in (:namedAreas)");
371 } else {
372 query = getSession().createQuery("select distinct description from TaxonDescription description left join description.elements element join element.area area join element.status status where area in (:namedAreas) and status = :status");
373 query.setParameter("status", status);
374 }
375 query.setParameterList("namedAreas", namedAreas);
376
377 if(pageSize != null) {
378 query.setMaxResults(pageSize);
379 if(pageNumber != null) {
380 query.setFirstResult(pageNumber * pageSize);
381 }
382 }
383
384 return (List<TaxonDescription>)query.list();
385 }
386
387 }