Merge branch 'release/5.11.0'
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / term / DefinedTermDaoImpl.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.term;
11
12 import java.net.URI;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.Enumeration;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Locale;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24 import org.hibernate.Criteria;
25 import org.hibernate.Query;
26 import org.hibernate.Session;
27 import org.hibernate.criterion.Criterion;
28 import org.hibernate.criterion.Disjunction;
29 import org.hibernate.criterion.Order;
30 import org.hibernate.criterion.Projections;
31 import org.hibernate.criterion.Restrictions;
32 import org.hibernate.envers.query.AuditEntity;
33 import org.hibernate.envers.query.AuditQuery;
34 import org.springframework.stereotype.Repository;
35
36 import eu.etaxonomy.cdm.model.common.AnnotationType;
37 import eu.etaxonomy.cdm.model.common.CdmBase;
38 import eu.etaxonomy.cdm.model.common.ExtensionType;
39 import eu.etaxonomy.cdm.model.common.Language;
40 import eu.etaxonomy.cdm.model.common.MarkerType;
41 import eu.etaxonomy.cdm.model.description.MeasurementUnit;
42 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
43 import eu.etaxonomy.cdm.model.description.State;
44 import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
45 import eu.etaxonomy.cdm.model.description.TextFormat;
46 import eu.etaxonomy.cdm.model.location.Country;
47 import eu.etaxonomy.cdm.model.location.NamedArea;
48 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
49 import eu.etaxonomy.cdm.model.location.NamedAreaType;
50 import eu.etaxonomy.cdm.model.location.ReferenceSystem;
51 import eu.etaxonomy.cdm.model.media.Media;
52 import eu.etaxonomy.cdm.model.media.RightsType;
53 import eu.etaxonomy.cdm.model.metadata.NamedAreaSearchField;
54 import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
55 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
56 import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
57 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
58 import eu.etaxonomy.cdm.model.name.Rank;
59 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
60 import eu.etaxonomy.cdm.model.occurrence.DerivationEventType;
61 import eu.etaxonomy.cdm.model.taxon.SynonymType;
62 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
63 import eu.etaxonomy.cdm.model.term.DefinedTerm;
64 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
65 import eu.etaxonomy.cdm.model.term.TermType;
66 import eu.etaxonomy.cdm.model.term.TermVocabulary;
67 import eu.etaxonomy.cdm.model.view.AuditEvent;
68 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
69 import eu.etaxonomy.cdm.persistence.dao.term.IDefinedTermDao;
70 import eu.etaxonomy.cdm.persistence.dto.TermDto;
71 import eu.etaxonomy.cdm.persistence.query.MatchMode;
72 import eu.etaxonomy.cdm.persistence.query.OrderHint;
73
74
75 /**
76 * @author a.kohlbecker
77 * @since 29.05.2008
78 * @version 1.0
79 */
80 @Repository
81 public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> implements IDefinedTermDao{
82 private static final Logger logger = Logger.getLogger(DefinedTermDaoImpl.class);
83
84 public DefinedTermDaoImpl() {
85 super(DefinedTermBase.class);
86 indexedClasses = new Class[25];
87 indexedClasses[0] = Rank.class;
88 indexedClasses[1] = AnnotationType.class;
89 indexedClasses[2] = ExtensionType.class;
90 indexedClasses[3] = Language.class;
91 indexedClasses[4] = MarkerType.class;
92 indexedClasses[5] = MeasurementUnit.class;
93 indexedClasses[6] = DefinedTerm.class;
94 indexedClasses[7] = PresenceAbsenceTerm.class;
95 indexedClasses[8] = State.class;
96 indexedClasses[9] = StatisticalMeasure.class;
97 indexedClasses[10] = TextFormat.class;
98 indexedClasses[11] = DerivationEventType.class;
99 indexedClasses[12] = NamedArea.class;
100 indexedClasses[13] = NamedAreaLevel.class;
101 indexedClasses[14] = NamedAreaType.class;
102 indexedClasses[15] = ReferenceSystem.class;
103 indexedClasses[16] = Country.class;
104 indexedClasses[17] = RightsType.class;
105 indexedClasses[18] = HybridRelationshipType.class;
106 indexedClasses[19] = NameRelationshipType.class;
107 indexedClasses[20] = NameTypeDesignationStatus.class;
108 indexedClasses[21] = NomenclaturalStatusType.class;
109 indexedClasses[22] = SpecimenTypeDesignationStatus.class;
110 indexedClasses[23] = SynonymType.class;
111 indexedClasses[24] = TaxonRelationshipType.class;
112 }
113
114 /**
115 * Searches by Label
116 * @see eu.etaxonomy.cdm.persistence.dao.common.ITitledDao#findByTitle(java.lang.String)
117 */
118 @Override
119 public List<DefinedTermBase> findByTitle(String queryString) {
120 return findByTitle(queryString, null);
121 }
122
123
124 /**
125 * Searches by Label
126 * @see eu.etaxonomy.cdm.persistence.dao.common.ITitledDao#findByTitle(java.lang.String, eu.etaxonomy.cdm.model.common.CdmBase)
127 */
128 @Override
129 public List<DefinedTermBase> findByTitle(String queryString, CdmBase sessionObject) {
130 checkNotInPriorView("DefinedTermDaoImpl.findByTitle(String queryString, CdmBase sessionObject)");
131 Session session = getSession();
132 if ( sessionObject != null ) {//attache the object to the session, TODO needed?
133 session.update(sessionObject);
134 }
135 Query query = session.createQuery("select term from DefinedTermBase term join fetch term.representations representation where representation.label = :label");
136 query.setParameter("label", queryString);
137 return query.list();
138
139 }
140
141 @Override
142 public List<DefinedTermBase> findByTitleAndClass(String queryString, Class<DefinedTermBase> clazz) {
143 checkNotInPriorView("DefinedTermDaoImpl.findByTitleAndClass(String queryString, Class<DefinedTermBase> clazz)");
144 Session session = getSession();
145 Criteria crit = session.createCriteria(clazz);
146 crit.add(Restrictions.ilike("persistentTitleCache", queryString));
147 List<DefinedTermBase> results = crit.list();
148 return results;
149 }
150
151 @Override
152 public List<DefinedTermBase> findByTitle(String queryString, MatchMode matchMode, int page, int pagesize, List<Criterion> criteria) {
153 //FIXME is query parametrised?
154 checkNotInPriorView("DefinedTermDaoImpl.findByTitle(String queryString, ITitledDao.MATCH_MODE matchMode, int page, int pagesize, List<Criterion> criteria)");
155 Criteria crit = getSession().createCriteria(type);
156 crit.add(Restrictions.ilike("titleCache", matchMode.queryStringFrom(queryString)));
157 crit.setMaxResults(pagesize);
158 int firstItem = (page - 1) * pagesize + 1;
159 crit.setFirstResult(firstItem);
160 List<DefinedTermBase> results = crit.list();
161 return results;
162 }
163
164
165 @Override
166 public Country getCountryByIso(String iso3166) {
167 // If iso639 = "" query returns non-unique result. We prevent this here:
168 if (StringUtils.isBlank(iso3166) || iso3166.length()<2 || iso3166.length()>3) { return null; }
169 AuditEvent auditEvent = getAuditEventFromContext();
170 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
171 Query query = getSession().createQuery("from Country where iso3166_A2 = :isoCode OR idInVocabulary = :isoCode");
172 query.setParameter("isoCode", iso3166);
173 return (Country) query.uniqueResult();
174 } else {
175 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(Country.class,auditEvent.getRevisionNumber());
176 query.add(AuditEntity.property("iso3166_A2").eq(iso3166));
177 query.add(AuditEntity.property("idInVocabulary").eq(iso3166));
178 return (Country) query.getSingleResult();
179 }
180 }
181
182 @Override
183 public <T extends DefinedTermBase> List<T> getDefinedTermByRepresentationText(String text, Class<T> clazz ) {
184 return getDefinedTermByRepresentationText(text,clazz,null,null);
185 }
186
187 @Override
188 public <T extends DefinedTermBase> List<T> getDefinedTermByRepresentationText(String text, Class<T> clazz, Integer pageSize,Integer pageNumber) {
189 checkNotInPriorView("DefinedTermDaoImpl.getDefinedTermByRepresentationText(String text, Class<T> clazz, Integer pageSize,Integer pageNumber)");
190
191 Criteria criteria = getCriteria(clazz);
192
193 criteria.createAlias("representations", "r").add(Restrictions.like("r.text", text));
194
195 addPageSizeAndNumber(criteria, pageSize, pageNumber);
196
197 @SuppressWarnings("unchecked")
198 List<T> result = criteria.list();
199 return result;
200 }
201
202 @Override
203 public long countDefinedTermByRepresentationText(String text, Class<? extends DefinedTermBase> clazz) {
204 checkNotInPriorView("DefinedTermDaoImpl.countDefinedTermByRepresentationText(String text, Class<? extends DefinedTermBase> clazz)");
205 Criteria criteria = getCriteria(clazz);
206
207 criteria.createAlias("representations", "r").add(Restrictions.like("r.text", text));
208
209 criteria.setProjection(Projections.rowCount());
210
211 return (Long)criteria.uniqueResult();
212 }
213
214 @Override
215 public <T extends DefinedTermBase> List<T> getDefinedTermByIdInVocabulary(String label, UUID vocUuid, Class<T> clazz, Integer pageSize, Integer pageNumber) {
216 checkNotInPriorView("DefinedTermDaoImpl.getDefinedTermByIdInVocabulary(String label, UUID vocUuid, Class<T> clazz, Integer pageSize, Integer pageNumber)");
217
218 Criteria criteria = getCriteria(clazz);
219
220 criteria.createAlias("vocabulary", "voc")
221 .add(Restrictions.like("voc.uuid", vocUuid))
222 .add(Restrictions.like("idInVocabulary", label, org.hibernate.criterion.MatchMode.EXACT));
223
224 addPageSizeAndNumber(criteria, pageSize, pageNumber);
225
226 @SuppressWarnings("unchecked")
227 List<T> result = criteria.list();
228 return result;
229 }
230
231 @Override
232 public <T extends DefinedTermBase> List<T> getDefinedTermByRepresentationAbbrev(String text, Class<T> clazz, Integer pageSize,Integer pageNumber) {
233 checkNotInPriorView("DefinedTermDaoImpl.getDefinedTermByRepresentationAbbrev(String abbrev, Class<T> clazz, Integer pageSize,Integer pageNumber)");
234
235 Criteria criteria = getCriteria(clazz);
236
237 criteria.createAlias("representations", "r").add(Restrictions.like("r.abbreviatedLabel", text));
238
239 addPageSizeAndNumber(criteria, pageSize, pageNumber);
240
241 @SuppressWarnings("unchecked")
242 List<T> result = criteria.list();
243 return result;
244 }
245
246 @Override
247 public long countDefinedTermByRepresentationAbbrev(String text, Class<? extends DefinedTermBase> clazz) {
248 checkNotInPriorView("DefinedTermDaoImpl.countDefinedTermByRepresentationAbbrev(String abbrev, Class<? extends DefinedTermBase> clazz)");
249 Criteria criteria = getCriteria(clazz);
250
251 criteria.createAlias("representations", "r").add(Restrictions.like("r.abbreviatedLabel", text));
252 criteria.setProjection(Projections.rowCount());
253
254 return (Long)criteria.uniqueResult();
255 }
256
257 @Override
258 public Language getLanguageByIso(String iso639) {
259 if (iso639.length() < 2 || iso639.length() > 3) {
260 logger.warn("Invalid length " + iso639.length() + " of ISO code. Length must be 2 or 3.");
261 return null;
262 }
263 boolean isIso639_1 = iso639.length() == 2;
264
265 String queryStr;
266 if (isIso639_1){
267 queryStr = "from Language where iso639_1 = :isoCode";
268 }else{
269 queryStr = "from Language where idInVocabulary = :isoCode and vocabulary.uuid = :vocUuid";
270 }
271 AuditEvent auditEvent = getAuditEventFromContext();
272 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
273 Query query = getSession().createQuery(queryStr);
274 query.setParameter("isoCode", iso639);
275 if (! isIso639_1){
276 query.setParameter("vocUuid", Language.uuidLanguageVocabulary);
277 }
278 return (Language) query.uniqueResult();
279 } else {
280 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(Language.class,auditEvent.getRevisionNumber());
281 if (isIso639_1){
282 query.add(AuditEntity.property("iso639_1").eq(iso639));
283 }else{
284 query.add(AuditEntity.property("iso639_2").eq(iso639));
285 query.add(AuditEntity.property("vocabulary.uuid").eq(Language.uuidLanguageVocabulary));
286 }
287
288 return (Language)query.getSingleResult();
289 }
290 }
291
292 /**
293 * FIXME this will result in a query per language - could you, given that iso codes
294 * are unique, use from Language where iso639_1 in (:isoCode) or iso639_2 in (:isoCode)
295 */
296 @Override
297 public List<Language> getLanguagesByIso(List<String> iso639List) {
298 List<Language> languages = new ArrayList<Language>(iso639List.size());
299 for (String iso639 : iso639List) {
300 languages.add(getLanguageByIso(iso639));
301 }
302 return languages;
303 }
304
305 @Override
306 public List<Language> getLanguagesByLocale(Enumeration<Locale> locales) {
307 List<Language> languages = new ArrayList<Language>();
308 while(locales.hasMoreElements()) {
309 Locale locale = locales.nextElement();
310 languages.add(getLanguageByIso(locale.getLanguage()));
311 }
312 return languages;
313 }
314
315 @Override
316 public long count(NamedAreaLevel level, NamedAreaType type) {
317 AuditEvent auditEvent = getAuditEventFromContext();
318 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
319 Criteria criteria = getCriteria(NamedArea.class);
320
321 if(level != null) {
322 criteria.add(Restrictions.eq("level",level));
323 }
324
325 if(type != null) {
326 criteria.add(Restrictions.eq("type", type));
327 }
328
329 criteria.setProjection(Projections.rowCount());
330
331 return (Long)criteria.uniqueResult();
332 } else {
333 AuditQuery query = makeAuditQuery(NamedArea.class, auditEvent);
334
335 if(level != null) {
336 query.add(AuditEntity.relatedId("level").eq(level.getId()));
337 }
338
339 if(type != null) {
340 query.add(AuditEntity.relatedId("type").eq(type.getId()));
341 }
342 query.addProjection(AuditEntity.id().count());
343 return (Long)query.getSingleResult();
344 }
345 }
346
347 @Override
348 public long countMedia(DefinedTermBase definedTerm) {
349 checkNotInPriorView("DefinedTermDaoImpl.countMedia(DefinedTermBase definedTerm)");
350 Query query = getSession().createQuery("select count(media) from DefinedTermBase definedTerm join definedTerm.media media where definedTerm = :definedTerm");
351 query.setParameter("definedTerm", definedTerm);
352
353 return (Long)query.uniqueResult();
354 }
355
356 @Override
357 public List<Media> getMedia(DefinedTermBase definedTerm, Integer pageSize, Integer pageNumber) {
358 checkNotInPriorView("DefinedTermDaoImpl.getMedia(DefinedTermBase definedTerm, Integer pageSize, Integer pageNumber)");
359 Query query = getSession().createQuery("select media from DefinedTermBase definedTerm join definedTerm.media media where definedTerm = :definedTerm");
360 query.setParameter("definedTerm", definedTerm);
361
362 addPageSizeAndNumber(query, pageSize, pageNumber);
363
364 @SuppressWarnings("unchecked")
365 List<Media> result = query.list();
366 return result;
367 }
368
369 @Override
370 public List<NamedArea> list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber) {
371 AuditEvent auditEvent = getAuditEventFromContext();
372 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
373 Criteria criteria = getCriteria(NamedArea.class);
374
375 if(level != null) {
376 criteria.add(Restrictions.eq("level",level));
377 }
378
379 if(type != null) {
380 criteria.add(Restrictions.eq("type", type));
381 }
382
383 addPageSizeAndNumber(criteria, pageSize, pageNumber);
384
385 @SuppressWarnings("unchecked")
386 List<NamedArea> result = criteria.list();
387 return result;
388 } else {
389 AuditQuery query = makeAuditQuery(NamedArea.class, auditEvent);
390
391 if(level != null) {
392 query.add(AuditEntity.relatedId("level").eq(level.getId()));
393 }
394
395 if(type != null) {
396 query.add(AuditEntity.relatedId("type").eq(type.getId()));
397 }
398
399 @SuppressWarnings("unchecked")
400 List<NamedArea> result = query.getResultList();
401 return result;
402 }
403 }
404
405 @Override
406 public List<NamedArea> list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber,
407 List<OrderHint> orderHints, List<String> propertyPaths) {
408
409 List<NamedArea> result;
410
411 AuditEvent auditEvent = getAuditEventFromContext();
412 if (auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
413 Criteria criteria = getCriteria(NamedArea.class);
414
415 if (level != null) {
416 criteria.add(Restrictions.eq("level", level));
417 }
418 if (type != null) {
419 criteria.add(Restrictions.eq("type", type));
420 }
421 addOrder(criteria,orderHints);
422 addPageSizeAndNumber(criteria, pageSize, pageNumber);
423
424 result = criteria.list();
425
426 } else {
427 AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(NamedArea.class,
428 auditEvent.getRevisionNumber());
429 if (level != null) {
430 query.add(AuditEntity.relatedId("level").eq(level.getId()));
431 }
432 if (type != null) {
433 query.add(AuditEntity.relatedId("type").eq(type.getId()));
434 }
435 result = query.getResultList();
436 }
437
438 defaultBeanInitializer.initializeAll(result, propertyPaths);
439
440 return result;
441 }
442
443
444 @Override
445 public <T extends DefinedTermBase> long countGeneralizationOf(T kindOf) {
446 AuditEvent auditEvent = getAuditEventFromContext();
447 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
448 Query query = getSession().createQuery("select count(term) from DefinedTermBase term where term.kindOf = :kindOf");
449 query.setParameter("kindOf", kindOf);
450 return (Long)query.uniqueResult();
451 } else {
452 AuditQuery query = makeAuditQuery(DefinedTermBase.class,auditEvent);
453 query.add(AuditEntity.relatedId("kindOf").eq(kindOf.getId()));
454 query.addProjection(AuditEntity.id().count());
455 return (Long)query.getSingleResult();
456 }
457 }
458
459 @Override
460 public <T extends DefinedTermBase> long countIncludes(Collection<T> partOf) {
461 if (partOf == null || partOf.isEmpty()){
462 return 0;
463 }
464 AuditEvent auditEvent = getAuditEventFromContext();
465 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
466 Query query = getSession().createQuery("select count(term) from DefinedTermBase term where term.partOf in (:partOf)");
467 query.setParameterList("partOf", partOf);
468 return (Long)query.uniqueResult();
469 } else {
470 long count = 0;
471 for(T t : partOf) {
472 AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
473 query.add(AuditEntity.relatedId("partOf").eq(t.getId()));
474 query.addProjection(AuditEntity.id().count());
475 count += (Long)query.getSingleResult();
476 }
477 return count;
478 }
479 }
480
481 @Override
482 public <T extends DefinedTermBase> List<T> getGeneralizationOf(T kindOf, Integer pageSize, Integer pageNumber) {
483 AuditEvent auditEvent = getAuditEventFromContext();
484 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
485 Query query = getSession().createQuery("select term from DefinedTermBase term where term.kindOf = :kindOf");
486 query.setParameter("kindOf", kindOf);
487
488 addPageSizeAndNumber(query, pageSize, pageNumber);
489
490 @SuppressWarnings("unchecked")
491 List<T> result = query.list();
492 return result;
493 } else {
494 AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
495 query.add(AuditEntity.relatedId("kindOf").eq(kindOf.getId()));
496
497 addPageSizeAndNumber(query, pageSize, pageNumber);
498
499 @SuppressWarnings("unchecked")
500 List<T> result = query.getResultList();
501 return result;
502 }
503 }
504
505 @Override
506 public <T extends DefinedTermBase> List<T> getIncludes(Collection<T> partOf, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
507 if (partOf == null || partOf.isEmpty()){
508 return new ArrayList<>();
509 }
510 AuditEvent auditEvent = getAuditEventFromContext();
511 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
512 Query query = getSession().createQuery("select term from DefinedTermBase term where term.partOf in (:partOf)");
513 query.setParameterList("partOf", partOf);
514
515 addPageSizeAndNumber(query, pageSize, pageNumber);
516
517 @SuppressWarnings("unchecked")
518 List<T> results = query.list();
519 defaultBeanInitializer.initializeAll(results, propertyPaths);
520 return results;
521 } else {
522 List<T> result = new ArrayList<T>();
523 for(T t : partOf) {
524 AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
525 query.add(AuditEntity.relatedId("partOf").eq(t.getId()));
526 addPageSizeAndNumber(query, pageSize, pageNumber);
527
528 result.addAll(query.getResultList());
529 }
530 defaultBeanInitializer.initializeAll(result, propertyPaths);
531 return result;
532 }
533 }
534
535 @Override
536 public <T extends DefinedTermBase> long countPartOf(Set<T> definedTerms) {
537 checkNotInPriorView("DefinedTermDaoImpl.countPartOf(Set<T> definedTerms)");
538 Query query = getSession().createQuery("select count(distinct definedTerm) from DefinedTermBase definedTerm join definedTerm.includes included where included in (:definedTerms)");
539 query.setParameterList("definedTerms", definedTerms);
540 return (Long)query.uniqueResult();
541 }
542
543 @Override
544 public <T extends DefinedTermBase> List<T> getPartOf(Set<T> definedTerms, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
545 checkNotInPriorView("DefinedTermDaoImpl.getPartOf(Set<T> definedTerms, Integer pageSize, Integer pageNumber)");
546 Query query = getSession().createQuery("select distinct definedTerm from DefinedTermBase definedTerm join definedTerm.includes included where included in (:definedTerms)");
547 query.setParameterList("definedTerms", definedTerms);
548
549 addPageSizeAndNumber(query, pageSize, pageNumber);
550
551 @SuppressWarnings("unchecked")
552 List<T> r = query.list();
553 /**
554 * For some weird reason, hibernate returns proxies (extending the superclass), not the actual class on this,
555 * despite querying the damn database and returning the discriminator along with the rest of the object properties!
556 *
557 * Probably a bug in hibernate, but we'll manually deproxy for now since the objects are initialized anyway, the
558 * performance implications are small (we're swapping one array of references for another, not hitting the db or
559 * cache).
560 */
561 List<T> results = new ArrayList<>();
562 if(!definedTerms.isEmpty()) {
563 for(T t : r) {
564 T deproxied = CdmBase.deproxy(t);
565 results.add(deproxied);
566 }
567 defaultBeanInitializer.initializeAll(results, propertyPaths);
568 }
569 return results;
570 }
571
572 @Override
573 public DefinedTermBase findByUri(URI uri) {
574 AuditEvent auditEvent = getAuditEventFromContext();
575 if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
576 Query query = getSession().createQuery("select term from DefinedTermBase term where term.uri = :uri");
577 query.setParameter("uri", uri);
578 return (DefinedTermBase<?>)query.uniqueResult();
579 } else {
580 AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
581 query.add(AuditEntity.property("uri").eq(uri));
582 return (DefinedTermBase<?>)query.getSingleResult();
583 }
584 }
585
586 @Override
587 public <T extends DefinedTermBase> List<T> listByTermType(TermType termType, Integer limit, Integer start,
588 List<OrderHint> orderHints, List<String> propertyPaths) {
589 Query query = getSession().createQuery("SELECT term FROM DefinedTermBase term WHERE term.termType = :termType");
590 query.setParameter("termType", termType);
591
592 @SuppressWarnings("unchecked")
593 List<T> result = query.list();
594
595 defaultBeanInitializer.initializeAll(result, propertyPaths);
596 return result;
597 }
598
599 @Override
600 public <TERM extends DefinedTermBase> List<TERM> listByTermClass(Class<TERM> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
601 // checkNotInPriorView("DefinedTermDaoImpl.listByTermClass(Class<TERM> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)");
602
603 Query query = getSession().createQuery("FROM " + clazz.getSimpleName());
604
605 @SuppressWarnings("unchecked")
606 List<TERM> result = query.list();
607
608 defaultBeanInitializer.initializeAll(result, propertyPaths);
609
610 return result;
611 }
612
613 @Override
614 public <S extends DefinedTermBase> List<S> list(Class<S> type, Integer limit, Integer start,
615 List<OrderHint> orderHints, List<String> propertyPath) {
616
617 return deduplicateResult(super.list(type, limit, start, orderHints, propertyPath));
618 }
619
620 /**
621 * Workaround for http://dev.e-taxonomy.eu/trac/ticket/5871 and #5945
622 * Terms with multiple representations return identical duplicates
623 * due to eager representation loading. We expect these duplicates to appear
624 * in line wo we only compare one term with its predecessor. If it already
625 * exists we remove it from the result.
626 * @param orginals
627 * @return
628 */
629 private <S extends DefinedTermBase<?>> List<S> deduplicateResult(List<S> orginals) {
630 List<S> result = new ArrayList<>();
631 Iterator<S> it = orginals.iterator();
632 S last = null;
633 while (it.hasNext()){
634 S a = it.next();
635 if (a != last){
636 if (!result.contains(a)){
637 result.add(a);
638 }
639 }
640 last = a;
641 }
642 return result;
643 }
644
645
646 @Override
647 public List<NamedArea> listNamedArea(List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode){
648 Session session = getSession();
649 // Query query = null;
650 // if (pattern != null){
651 // if (vocs != null && !vocs.isEmpty()){
652 // query = session.createQuery("from NamedArea where titleCache like :pattern and vocabulary in :vocs ORDER BY titleCache");
653 // query.setParameterList("vocs", vocs);
654 // }else{
655 // query = session.createQuery("from NamedArea where titleCache like :pattern ORDER BY titleCache");
656 // }
657 // pattern = pattern.replace("*", "%");
658 // pattern = pattern.replace("?", "_");
659 // pattern = pattern + "%";
660 // query.setParameter("pattern", pattern);
661 //
662 // } else {
663 // query = session.createQuery("FROM NamedArea WHERE vocabulary IN :vocs ORDER BY titleCache");
664 // query.setParameterList("vocs", vocs);
665 // }
666 // if (limit != null && limit > 0){
667 // query.setMaxResults(limit);
668 // }
669
670 Criteria crit = getSession().createCriteria(type, "namedArea");
671 if (!StringUtils.isBlank(pattern)){
672 if (matchmode == MatchMode.EXACT) {
673 crit.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(pattern)));
674 } else {
675 // crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
676 crit.add(Restrictions.like("titleCache", matchmode.queryStringFrom(pattern)));
677 }
678 }
679 if (limit != null && limit >= 0) {
680 crit.setMaxResults(limit);
681 }
682
683 if (vocs != null &&!vocs.isEmpty()){
684 crit.createAlias("namedArea.vocabulary", "voc");
685 Disjunction or = Restrictions.disjunction();
686 for (TermVocabulary voc: vocs){
687 Criterion criterion = Restrictions.eq("voc.id", voc.getId());
688 or.add(criterion);
689 }
690 crit.add(or);
691 }
692
693 crit.addOrder(Order.asc("titleCache"));
694 if (limit == null){
695 limit = 1;
696 }
697 int firstItem = (pageNumber - 1) * limit;
698
699 crit.setFirstResult(0);
700 @SuppressWarnings("unchecked")
701 List<NamedArea> results = crit.list();
702 return results;
703 }
704
705
706 @Override
707 public List<NamedArea> listNamedAreaByAbbrev(List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode, NamedAreaSearchField abbrevType){
708 Session session = getSession();
709
710 Criteria crit = getSession().createCriteria(type, "namedArea");
711 if (!StringUtils.isBlank(pattern)){
712 if (matchmode == MatchMode.EXACT) {
713 crit.add(Restrictions.eq(abbrevType.getKey(), matchmode.queryStringFrom(pattern)));
714 } else {
715 // crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
716 crit.add(Restrictions.like(abbrevType.getKey(), matchmode.queryStringFrom(pattern)));
717 }
718 }
719 if (limit != null && limit >= 0) {
720 crit.setMaxResults(limit);
721 }
722
723 if (vocs != null &&!vocs.isEmpty()){
724 crit.createAlias("namedArea.vocabulary", "voc");
725 Disjunction or = Restrictions.disjunction();
726 for (TermVocabulary voc: vocs){
727 Criterion criterion = Restrictions.eq("voc.id", voc.getId());
728 or.add(criterion);
729 }
730 crit.add(or);
731 }
732
733 crit.addOrder(Order.asc(abbrevType.getKey()));
734 if (limit == null){
735 limit = 1;
736 }
737 int firstItem = (pageNumber - 1) * limit;
738
739 crit.setFirstResult(0);
740 @SuppressWarnings("unchecked")
741 List<NamedArea> results = crit.list();
742 return results;
743 }
744
745 @Override
746 public long count(List<TermVocabulary> vocs, String pattern){
747 Session session = getSession();
748 Query query = null;
749 if (pattern != null){
750 if (vocs != null && !vocs.isEmpty()){
751 query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE titleCache LIKE :pattern AND vocabulary IN :vocs");
752 query.setParameterList("vocs", vocs);
753 }else{
754 query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE titleCache LIKE :pattern ");
755 }
756 pattern = pattern.replace("*", "%");
757 pattern = pattern.replace("?", "_");
758 pattern = pattern + "%";
759 query.setParameter("pattern", pattern);
760
761 } else {
762 query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE vocabulary IN :vocs");
763 query.setParameterList("vocs", vocs);
764 }
765
766
767 @SuppressWarnings("unchecked")
768 Long result = (Long) query.uniqueResult();
769 return result;
770 }
771
772 @Override
773 public Collection<TermDto> getIncludesAsDto(
774 TermDto parentTerm) {
775 String queryString = TermDto.getTermDtoSelect()
776 + "where a.partOf.uuid = :parentUuid";
777 Query query = getSession().createQuery(queryString);
778 query.setParameter("parentUuid", parentTerm.getUuid());
779
780 @SuppressWarnings("unchecked")
781 List<Object[]> result = query.list();
782
783 List<TermDto> list = TermDto.termDtoListFrom(result);
784 return list;
785 }
786
787 @Override
788 public Collection<TermDto> getKindOfsAsDto(
789 TermDto parentTerm) {
790 String queryString = TermDto.getTermDtoSelect()
791 + "where a.kindOf.uuid = :parentUuid";
792 Query query = getSession().createQuery(queryString);
793 query.setParameter("parentUuid", parentTerm.getUuid());
794
795 @SuppressWarnings("unchecked")
796 List<Object[]> result = query.list();
797
798 List<TermDto> list = TermDto.termDtoListFrom(result);
799 return list;
800 }
801
802
803 @Override
804 public Collection<TermDto> findByTitleAsDto(String title, TermType termType) {
805 String queryString = TermDto.getTermDtoSelect()
806 + " where a.titleCache like :title "
807 + (termType!=null?" and a.termType = :termType ":"");
808 Query query = getSession().createQuery(queryString);
809 query.setParameter("title", "%"+title+"%");
810 if(termType!=null){
811 query.setParameter("termType", termType);
812 }
813
814 @SuppressWarnings("unchecked")
815 List<Object[]> result = query.list();
816
817 List<TermDto> list = TermDto.termDtoListFrom(result);
818 return list;
819 }
820
821 @Override
822 public Collection<TermDto> findByTypeAsDto(TermType termType) {
823 if (termType == null){
824 return null;
825 }
826 String queryString = TermDto.getTermDtoSelect()
827 + " where a.termType = :termType ";
828 Query query = getSession().createQuery(queryString);
829
830 if(termType!=null){
831 query.setParameter("termType", termType);
832 }
833
834 @SuppressWarnings("unchecked")
835 List<Object[]> result = query.list();
836
837 List<TermDto> list = TermDto.termDtoListFrom(result);
838 return list;
839 }
840
841 @Override
842 public Collection<TermDto> findByUriAsDto(URI uri, String termLabel, TermType termType) {
843 String queryString = TermDto.getTermDtoSelect()
844 + " where a.uri like :uri "
845 + (termType!=null?" and a.termType = :termType ":"")
846 + (termLabel!=null?" and a.titleCache = :termLabel ":"")
847 ;
848 Query query = getSession().createQuery(queryString);
849 query.setParameter("uri", uri.toString());
850 if(termLabel!=null){
851 query.setParameter("termLabel", "%"+termLabel+"%");
852 }
853 if(termType!=null){
854 query.setParameter("termType", termType);
855 }
856
857 @SuppressWarnings("unchecked")
858 List<Object[]> result = query.list();
859
860 List<TermDto> list = TermDto.termDtoListFrom(result);
861 return list;
862 }
863
864 /**
865 * {@inheritDoc}
866 */
867 @Override
868 public List<NamedArea> listNamedArea(List<TermVocabulary> vocs, Integer limit, String pattern) {
869
870 return listNamedArea(vocs, 0, limit, pattern, MatchMode.BEGINNING);
871
872 }
873
874 @Override
875 public List<NamedArea> listNamedAreaByAbbrev(List<TermVocabulary> vocs, Integer limit, String pattern, NamedAreaSearchField type) {
876
877 return listNamedAreaByAbbrev(vocs, 0, limit, pattern, MatchMode.BEGINNING, type);
878
879 }
880
881 @Override
882 public List<TermDto> getSupportedStatesForFeature(UUID featureUuid){
883 List<TermDto> list = new ArrayList<>();
884 String supportedCategoriesQueryString = "SELECT cat.uuid "
885 + "from DefinedTermBase t "
886 + "join t.supportedCategoricalEnumerations as cat "
887 + "where t.uuid = :featureUuid";
888 Query supportedCategoriesQuery = getSession().createQuery(supportedCategoriesQueryString);
889 supportedCategoriesQuery.setParameter("featureUuid", featureUuid);
890 List<UUID> supportedCategories = supportedCategoriesQuery.list();
891 if(supportedCategories.isEmpty()){
892 return list;
893 }
894
895 String queryString = TermDto.getTermDtoSelect()
896 + "where v.uuid in (:supportedCategories) "
897 + "order by a.titleCache";
898 Query query = getSession().createQuery(queryString);
899 query.setParameterList("supportedCategories", supportedCategories);
900
901 @SuppressWarnings("unchecked")
902 List<Object[]> result = query.list();
903
904 list = TermDto.termDtoListFrom(result);
905 return list;
906 }
907
908 @Override
909 public Collection<TermDto> findByUUIDsAsDto(List<UUID> uuidList) {
910 List<TermDto> list = new ArrayList<>();
911 if (uuidList == null || uuidList.isEmpty()){
912 return null;
913 }
914
915 String queryString = TermDto.getTermDtoSelect()
916 + "where a.uuid in :uuidList "
917 + "order by a.titleCache";
918 Query query = getSession().createQuery(queryString);
919 query.setParameterList("uuidList", uuidList);
920
921 @SuppressWarnings("unchecked")
922 List<Object[]> result = query.list();
923
924 list = TermDto.termDtoListFrom(result);
925 return list;
926 }
927
928 }