Project

General

Profile

Download (36 KB) Statistics
| Branch: | Tag: | Revision:
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.Map;
16
import java.util.Set;
17
import java.util.UUID;
18

    
19
import org.apache.commons.lang.ArrayUtils;
20
import org.apache.log4j.Logger;
21
import org.hibernate.Criteria;
22
import org.hibernate.Query;
23
import org.hibernate.criterion.ProjectionList;
24
import org.hibernate.criterion.Projections;
25
import org.hibernate.criterion.Restrictions;
26
import org.hibernate.envers.query.AuditEntity;
27
import org.hibernate.envers.query.AuditQuery;
28
import org.springframework.beans.factory.annotation.Qualifier;
29
import org.springframework.stereotype.Repository;
30

    
31
import eu.etaxonomy.cdm.model.common.LSID;
32
import eu.etaxonomy.cdm.model.common.MarkerType;
33
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
34
import eu.etaxonomy.cdm.model.description.DescriptionBase;
35
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
36
import eu.etaxonomy.cdm.model.description.Feature;
37
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
38
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
39
import eu.etaxonomy.cdm.model.description.SpecimenDescription;
40
import eu.etaxonomy.cdm.model.description.TaxonDescription;
41
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
42
import eu.etaxonomy.cdm.model.location.NamedArea;
43
import eu.etaxonomy.cdm.model.media.Media;
44
import eu.etaxonomy.cdm.model.name.TaxonName;
45
import eu.etaxonomy.cdm.model.taxon.Taxon;
46
import eu.etaxonomy.cdm.model.term.DefinedTerm;
47
import eu.etaxonomy.cdm.model.view.AuditEvent;
48
import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException;
49
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
50
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
51
import eu.etaxonomy.cdm.persistence.dto.TermDto;
52
import eu.etaxonomy.cdm.persistence.query.MatchMode;
53
import eu.etaxonomy.cdm.persistence.query.OrderHint;
54

    
55
@Repository
56
@Qualifier("descriptionDaoImpl")
57
public class DescriptionDaoImpl extends IdentifiableDaoBase<DescriptionBase> implements IDescriptionDao{
58

    
59
    private static final Logger logger = Logger.getLogger(DescriptionDaoImpl.class);
60

    
61
    public DescriptionDaoImpl() {
62
        super(DescriptionBase.class);
63
        indexedClasses = new Class[3];
64
        indexedClasses[0] = TaxonDescription.class;
65
        indexedClasses[1] = TaxonNameDescription.class;
66
        indexedClasses[2] = SpecimenDescription.class;
67
    }
68

    
69
//    @Override  //Override for testing
70
//    public DescriptionBase load(UUID uuid, List<String> propertyPaths){
71
//    	DescriptionBase bean = findByUuid(uuid);
72
//        if(bean == null){
73
//            return bean;
74
//        }
75
//        defaultBeanInitializer.initialize(bean, propertyPaths);
76
//
77
//        return bean;
78
//    }
79

    
80
    @Override
81
    public long countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm status) {
82
        checkNotInPriorView("DescriptionDaoImpl.countDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status)");
83
        Query query = null;
84

    
85
        if(status == null) {
86
            query = getSession().createQuery("select count(distinct description) from TaxonDescription description left join description.descriptionElements element join element.area area where area in (:namedAreas)");
87
        } else {
88
            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");
89
            query.setParameter("status", status);
90
        }
91
        query.setParameterList("namedAreas", namedAreas);
92

    
93
        return (Long)query.uniqueResult();
94
    }
95

    
96
    @Override
97
    public <T extends DescriptionElementBase> long countDescriptionElements(DescriptionBase description, Set<Feature> features, Class<T> clazz) {
98
        return countDescriptionElements(description, null, features, clazz);
99
    }
100

    
101
    @Override
102
    public <T extends DescriptionElementBase> long countDescriptionElements(DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
103
            Set<Feature> features, Class<T> clazz) {
104
        AuditEvent auditEvent = getAuditEventFromContext();
105
        if (clazz == null){
106
            clazz = (Class<T>)DescriptionElementBase.class;
107
        }
108
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
109
            Criteria criteria = getCriteria(clazz);
110

    
111
            if(description != null) {
112
                criteria.add(Restrictions.eq("inDescription", description));
113
            }
114

    
115
            if(descriptionType != null) {
116
                criteria.createAlias("inDescription", "d").add(Restrictions.eq("d.class", descriptionType));
117
            }
118

    
119
            if(features != null && !features.isEmpty()) {
120
                criteria.add(Restrictions.in("feature", features));
121
            }
122

    
123
            criteria.setProjection(Projections.rowCount());
124

    
125
            return (Long)criteria.uniqueResult();
126
        } else {
127
            if(features != null && !features.isEmpty()) {
128
                long count = 0;
129
                for(Feature f : features) {
130
                    AuditQuery query = null;
131
                    query = makeAuditQuery(clazz, auditEvent);
132

    
133
                    if(description != null) {
134
                        query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
135
                    }
136

    
137
                    if(descriptionType != null) {
138
                        query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
139
                    }
140

    
141
                    query.add(AuditEntity.relatedId("feature").eq(f.getId()));
142
                    query.addProjection(AuditEntity.id().count());
143
                    count += (Long)query.getSingleResult();
144
                }
145

    
146
                return count;
147
            } else {
148
                AuditQuery query = makeAuditQuery(clazz, auditEvent);
149

    
150
                if(description != null) {
151
                    query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
152
                }
153
                if(descriptionType != null) {
154
                    query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
155
                }
156

    
157
                query.addProjection(AuditEntity.id().count());
158
                return (Long)query.getSingleResult();
159
            }
160
        }
161
    }
162

    
163
    @Override
164
    public long countDescriptions(Class<? extends DescriptionBase> clazz, Boolean hasImages, Boolean hasText, Set<Feature> features) {
165
        checkNotInPriorView("DescriptionDaoImpl.countDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText, Set<Feature> features)");
166

    
167
        Criteria inner = getCriteria(clazz);
168

    
169
        Criteria elementsCriteria = inner.createCriteria("descriptionElements");
170
        if(hasText != null) {
171
            if(hasText) {
172
                elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
173
            } else {
174
                elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
175
            }
176
        }
177

    
178
        if(hasImages != null) {
179
            if(hasImages) {
180
                elementsCriteria.add(Restrictions.isNotEmpty("media"));
181
            } else {
182
                elementsCriteria.add(Restrictions.isEmpty("media"));
183
            }
184
        }
185

    
186
        if(features != null && !features.isEmpty()) {
187
            elementsCriteria.add(Restrictions.in("feature", features));
188
        }
189

    
190
        inner.setProjection(Projections.countDistinct("id"));
191

    
192
        return (Long)inner.uniqueResult();
193
    }
194

    
195
    @Override
196
    public long countTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes,
197
            Set<NamedArea> geographicalScopes, Set<MarkerType> markerTypes) {
198
        AuditEvent auditEvent = getAuditEventFromContext();
199
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
200
            Criteria criteria = getCriteria(TaxonDescription.class);
201

    
202
            if(taxon != null) {
203
                criteria.add(Restrictions.eq("taxon", taxon));
204
            }
205

    
206
            if(scopes != null && !scopes.isEmpty()) {
207
                Set<Integer> scopeIds = new HashSet<>();
208
                for(DefinedTerm s : scopes) {
209
                    scopeIds.add(s.getId());
210
                }
211
                criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
212
            }
213

    
214
            if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
215
                Set<Integer> geoScopeIds = new HashSet<>();
216
                for(NamedArea n : geographicalScopes) {
217
                    geoScopeIds.add(n.getId());
218
                }
219
                criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
220
            }
221

    
222
            addMarkerTypesCriterion(markerTypes, criteria);
223

    
224
            criteria.setProjection(Projections.rowCount());
225

    
226
            return (Long)criteria.uniqueResult();
227
        } else {
228
            if((scopes == null || scopes.isEmpty())&& (geographicalScopes == null || geographicalScopes.isEmpty()) && (markerTypes == null || markerTypes.isEmpty())) {
229
                AuditQuery query = makeAuditQuery(TaxonDescription.class,auditEvent);
230
                if(taxon != null) {
231
                    query.add(AuditEntity.relatedId("taxon").eq(taxon.getId()));
232
                }
233

    
234
                query.addProjection(AuditEntity.id().count());
235

    
236
                return (Long)query.getSingleResult();
237
            } else {
238
                throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
239
            }
240
        }
241
    }
242

    
243
    /**
244
     * @param markerTypes
245
     * @param criteria
246
     *
247
     */
248
    //TODO move to AnnotatableEntityDao(?)
249
    private void addMarkerTypesCriterion(Set<MarkerType> markerTypes, Criteria criteria) {
250

    
251
        if(markerTypes != null && !markerTypes.isEmpty()) {
252
            Set<Integer> markerTypeIds = new HashSet<Integer>();
253
            for(MarkerType markerType : markerTypes) {
254
                markerTypeIds.add(markerType.getId());
255
            }
256
            criteria.createCriteria("markers").add(Restrictions.eq("flag", true))
257
                    .createAlias("markerType", "mt")
258
                     .add(Restrictions.in("mt.id", markerTypeIds));
259
        } else if (markerTypes != null && markerTypes.isEmpty()){
260
            //AT: added in case the projects requires an third state description, An empty Marker type set
261
        }
262
    }
263
    @Override
264
    public <T extends DescriptionElementBase> List<T> getDescriptionElements(
265
            DescriptionBase description, Set<Feature> features,
266
            Class<T> clazz, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
267
        return getDescriptionElements(description, null, features, clazz, pageSize, pageNumber, propertyPaths);
268
    }
269

    
270
    @Override
271
    public <T extends DescriptionElementBase> List<T> getDescriptionElements(
272
            DescriptionBase description, Class<? extends DescriptionBase> descriptionType,
273
            Set<Feature> features,
274
            Class<T> clazz,
275
            Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
276

    
277
        AuditEvent auditEvent = getAuditEventFromContext();
278
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
279
            Criteria criteria = null;
280
            if(clazz == null) {
281
                criteria = getSession().createCriteria(DescriptionElementBase.class);
282
            } else {
283
                criteria = getSession().createCriteria(clazz);
284
            }
285

    
286
            if(description != null) {
287
                criteria.add(Restrictions.eq("inDescription", description));
288
            }
289
            if(descriptionType != null) {
290
                criteria.createAlias("inDescription", "d").add(Restrictions.eq("d.class", descriptionType));
291
            }
292

    
293
            if(features != null && !features.isEmpty()) {
294
                criteria.add(Restrictions.in("feature", features));
295
            }
296

    
297
            if(pageSize != null) {
298
                criteria.setMaxResults(pageSize);
299
                if(pageNumber != null) {
300
                    criteria.setFirstResult(pageNumber * pageSize);
301
                }
302
            }
303

    
304
            List<T> results = criteria.list();
305

    
306
            defaultBeanInitializer.initializeAll(results, propertyPaths);
307

    
308
            return results;
309
        } else {
310
            List<T> result = new ArrayList<T>();
311
            if(features != null && !features.isEmpty()) {
312

    
313
                for(Feature f : features) {
314
                    AuditQuery query = null;
315
                    if(clazz == null) {
316
                        query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
317
                    } else {
318
                        query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
319
                    }
320

    
321
                    if(description != null) {
322
                        query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
323
                    }
324

    
325
                    if(descriptionType != null) {
326
                        query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
327
                    }
328

    
329
                    query.add(AuditEntity.relatedId("feature").eq(f.getId()));
330
                    result.addAll(query.getResultList());
331
                }
332
            } else {
333
                AuditQuery query = null;
334
                if(clazz == null) {
335
                    query = getAuditReader().createQuery().forEntitiesAtRevision(DescriptionElementBase.class,auditEvent.getRevisionNumber());
336
                } else {
337
                    query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
338
                }
339

    
340
                if(description != null) {
341
                    query.add(AuditEntity.relatedId("inDescription").eq(description.getId()));
342
                }
343

    
344
                if(descriptionType != null) {
345
                    query.add(AuditEntity.property("inDescription.class").eq(descriptionType));
346
                }
347

    
348
                result = query.getResultList();
349
            }
350

    
351
            defaultBeanInitializer.initializeAll(result, propertyPaths);
352

    
353
            return result;
354
        }
355
    }
356

    
357
    @Override
358
    public List<TaxonDescription> listTaxonDescriptions(Taxon taxon, Set<DefinedTerm> scopes, Set<NamedArea> geographicalScopes, Set<MarkerType> markerTypes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
359
        AuditEvent auditEvent = getAuditEventFromContext();
360
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
361
            Criteria criteria = getSession().createCriteria(TaxonDescription.class);
362

    
363
            if(taxon != null) {
364
                criteria.add(Restrictions.eq("taxon", taxon));
365
            }
366

    
367
            if(scopes != null && !scopes.isEmpty()) {
368
                Set<Integer> scopeIds = new HashSet<Integer>();
369
                for(DefinedTerm s : scopes) {
370
                    scopeIds.add(s.getId());
371
                }
372
                criteria.createCriteria("scopes").add(Restrictions.in("id", scopeIds));
373
            }
374

    
375
            if(geographicalScopes != null && !geographicalScopes.isEmpty()) {
376
                Set<Integer> geoScopeIds = new HashSet<Integer>();
377
                for(NamedArea n : geographicalScopes) {
378
                    geoScopeIds.add(n.getId());
379
                }
380
                criteria.createCriteria("geoScopes").add(Restrictions.in("id", geoScopeIds));
381
            }
382

    
383
            addMarkerTypesCriterion(markerTypes, criteria);
384

    
385
            if(pageSize != null) {
386
                criteria.setMaxResults(pageSize);
387
                if(pageNumber != null) {
388
                    criteria.setFirstResult(pageNumber * pageSize);
389
                }
390
            }
391

    
392
            List<TaxonDescription> results = criteria.list();
393

    
394
            defaultBeanInitializer.initializeAll(results, propertyPaths);
395

    
396
            return results;
397
        } else {
398
            if((scopes == null || scopes.isEmpty())&& (geographicalScopes == null || geographicalScopes.isEmpty())&& (markerTypes == null || markerTypes.isEmpty())) {
399
                AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonDescription.class,auditEvent.getRevisionNumber());
400
                if(taxon != null) {
401
                    query.add(AuditEntity.relatedId("taxon").eq(taxon.getId()));
402
                }
403

    
404
                if(pageSize != null) {
405
                    query.setMaxResults(pageSize);
406
                    if(pageNumber != null) {
407
                        query.setFirstResult(pageNumber * pageSize);
408
                    } else {
409
                        query.setFirstResult(0);
410
                    }
411
                }
412

    
413
                List<TaxonDescription> results = query.getResultList();
414
                defaultBeanInitializer.initializeAll(results, propertyPaths);
415
                return results;
416
            } else {
417
                throw new OperationNotSupportedInPriorViewException("countTaxonDescriptions(Taxon taxon, Set<Scope> scopes,Set<NamedArea> geographicalScopes)");
418
            }
419
        }
420
    }
421

    
422
    @Override
423
    public List<TaxonNameDescription> getTaxonNameDescriptions(TaxonName name, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
424
        AuditEvent auditEvent = getAuditEventFromContext();
425
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
426
            Criteria criteria = getSession().createCriteria(TaxonNameDescription.class);
427

    
428
          if(name != null) {
429
              criteria.add(Restrictions.eq("taxonName", name));
430
          }
431

    
432
          if(pageSize != null) {
433
              criteria.setMaxResults(pageSize);
434
              if(pageNumber != null) {
435
                  criteria.setFirstResult(pageNumber * pageSize);
436
              }
437
          }
438

    
439
          List<TaxonNameDescription> results = criteria.list();
440

    
441
          defaultBeanInitializer.initializeAll(results, propertyPaths);
442

    
443
          return results;
444
        } else {
445
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonNameDescription.class,auditEvent.getRevisionNumber());
446

    
447
            if(name != null) {
448
                query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
449
            }
450

    
451
            if(pageSize != null) {
452
                  query.setMaxResults(pageSize);
453
                  if(pageNumber != null) {
454
                      query.setFirstResult(pageNumber * pageSize);
455
                  }
456
            }
457

    
458
            List<TaxonNameDescription> results = query.getResultList();
459

    
460
            defaultBeanInitializer.initializeAll(results, propertyPaths);
461

    
462
            return results;
463
        }
464

    
465
    }
466

    
467
    @Override
468
    public long countTaxonNameDescriptions(TaxonName name) {
469
        AuditEvent auditEvent = getAuditEventFromContext();
470
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
471
            Criteria criteria = getCriteria(TaxonNameDescription.class);
472

    
473
            if(name != null) {
474
                criteria.add(Restrictions.eq("taxonName", name));
475
            }
476

    
477
            criteria.setProjection(Projections.rowCount());
478

    
479
            return (Long)criteria.uniqueResult();
480
        } else {
481
            AuditQuery query = makeAuditQuery(TaxonNameDescription.class,auditEvent);
482

    
483
            if(name != null) {
484
                query.add(AuditEntity.relatedId("taxonName").eq(name.getId()));
485
            }
486

    
487
            query.addProjection(AuditEntity.id().count());
488
            return (Long)query.getSingleResult();
489
        }
490
    }
491

    
492
    /**
493
     * Should use a DetachedCriteria & subquery, but HHH-158 prevents this, for now.
494
     *
495
     * e.g. DetachedCriteria inner = DestachedCriteria.forClass(type);
496
     *
497
     * outer.add(Subqueries.propertyIn("id", inner));
498
     */
499
    @Override
500
    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) {
501
        checkNotInPriorView("DescriptionDaoImpl.listDescriptions(Class<TYPE> type, Boolean hasImages, Boolean hasText,	Set<Feature> features, Integer pageSize, Integer pageNumber)");
502
        Criteria inner = getCriteria(clazz);
503

    
504
        Criteria elementsCriteria = inner.createCriteria("descriptionElements");
505
        if(hasText != null) {
506
            if(hasText) {
507
                elementsCriteria.add(Restrictions.isNotEmpty("multilanguageText"));
508
            } else {
509
                elementsCriteria.add(Restrictions.isEmpty("multilanguageText"));
510
            }
511
        }
512

    
513
        if(hasImages != null) {
514
            if(hasImages) {
515
                elementsCriteria.add(Restrictions.isNotEmpty("media"));
516
            } else {
517
                elementsCriteria.add(Restrictions.isEmpty("media"));
518
            }
519
        }
520

    
521
        if(features != null && !features.isEmpty()) {
522
            elementsCriteria.add(Restrictions.in("feature", features));
523
        }
524

    
525
        inner.setProjection(Projections.distinct(Projections.id()));
526

    
527
        @SuppressWarnings("unchecked")
528
        List<Object> intermediateResult = inner.list();
529

    
530
        if(intermediateResult.isEmpty()) {
531
            return new ArrayList<>();
532
        }
533

    
534
        Integer[] resultIds = new Integer[intermediateResult.size()];
535
        for(int i = 0; i < resultIds.length; i++) {
536
                resultIds[i] = (Integer)intermediateResult.get(i);
537
        }
538

    
539
        Criteria outer = getCriteria(clazz);
540

    
541
        outer.add(Restrictions.in("id", resultIds));
542
        addOrder(outer, orderHints);
543

    
544
        addPageSizeAndNumber(outer, pageSize, pageNumber);
545

    
546
        @SuppressWarnings({ "unchecked", "rawtypes" })
547
        List<DescriptionBase> results = outer.list();
548
        defaultBeanInitializer.initializeAll(results, propertyPaths);
549
        return results;
550
    }
551

    
552
    @Override
553
    public List<TaxonDescription> searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTerm status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
554
        checkNotInPriorView("DescriptionDaoImpl.searchDescriptionByDistribution(Set<NamedArea> namedAreas, PresenceAbsenceTermBase status, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
555

    
556
        Criteria criteria = getSession().createCriteria(TaxonDescription.class);
557
        Criteria elements = criteria.createCriteria("descriptionElements", "descriptionElement", Criteria.LEFT_JOIN);
558
        elements.add(Restrictions.in("area", namedAreas.toArray()));
559

    
560
        if(status != null) {
561
            elements.add(Restrictions.eq("status", status));
562
        }
563

    
564
        ProjectionList projectionList = Projections.projectionList().add(Projections.id());
565

    
566
        if(orderHints != null && !orderHints.isEmpty()) {
567
            for(OrderHint orderHint : orderHints) {
568
                projectionList = projectionList.add(Projections.property(orderHint.getPropertyName()));
569
            }
570
        }
571

    
572
        criteria.setProjection(Projections.distinct(projectionList));
573

    
574
        if(pageSize != null) {
575
            criteria.setMaxResults(pageSize);
576
            if(pageNumber != null) {
577
                criteria.setFirstResult(pageNumber * pageSize);
578
            }
579
        }
580

    
581
        addOrder(criteria,orderHints);
582

    
583
        @SuppressWarnings("unchecked")
584
        List<Object> intermediateResult = criteria.list();
585

    
586
        if(intermediateResult.isEmpty()) {
587
            return new ArrayList<>();
588
        }
589

    
590
        Integer[] resultIds = new Integer[intermediateResult.size()];
591
        for(int i = 0; i < resultIds.length; i++) {
592
            if(orderHints == null || orderHints.isEmpty()) {
593
                resultIds[i] = (Integer)intermediateResult.get(i);
594
            } else {
595
              resultIds[i] = ((Number)((Object[])intermediateResult.get(i))[0]).intValue();
596
            }
597
        }
598

    
599
        criteria = getSession().createCriteria(TaxonDescription.class);
600
        criteria.add(Restrictions.in("id", resultIds));
601
        addOrder(criteria,orderHints);
602

    
603
        @SuppressWarnings("unchecked")
604
        List<TaxonDescription> results = criteria.list();
605
        defaultBeanInitializer.initializeAll(results, propertyPaths);
606
        return results;
607
    }
608

    
609
    @Override
610
    public List<CommonTaxonName> searchDescriptionByCommonName(String queryString, MatchMode matchMode, Integer pageSize, Integer pageNumber) {
611

    
612
        Criteria crit = getSession().createCriteria(CommonTaxonName.class);
613
        if (matchMode == MatchMode.EXACT) {
614
            crit.add(Restrictions.eq("name", matchMode.queryStringFrom(queryString)));
615
        } else {
616
            crit.add(Restrictions.ilike("name", matchMode.queryStringFrom(queryString)));
617
        }
618

    
619
        if(pageSize != null) {
620
            crit.setMaxResults(pageSize);
621
            if(pageNumber != null) {
622
                crit.setFirstResult(pageNumber * pageSize);
623
            }
624
        }
625
        @SuppressWarnings("unchecked")
626
        List<CommonTaxonName> results = crit.list();
627
        return results;
628
    }
629

    
630
    @Override
631
    public Integer countDescriptionByCommonName(String queryString, MatchMode matchMode) {
632
        //TODO inprove performance
633
        List<CommonTaxonName> results =  searchDescriptionByCommonName(queryString, matchMode, null, null);
634
        return results.size();
635
    }
636

    
637
    @Override
638
    public DescriptionBase find(LSID lsid) {
639
        DescriptionBase<?> descriptionBase = super.find(lsid);
640
        if(descriptionBase != null) {
641
            List<String> propertyPaths = new ArrayList<>();
642
            propertyPaths.add("createdBy");
643
            propertyPaths.add("updatedBy");
644
            propertyPaths.add("taxon");
645
            propertyPaths.add("taxonName");
646
            propertyPaths.add("descriptionElements");
647
            propertyPaths.add("descriptionElements.createdBy");
648
            propertyPaths.add("descriptionElements.updatedBy");
649
            propertyPaths.add("descriptionElements.feature");
650
            propertyPaths.add("descriptionElements.multilanguageText");
651
            propertyPaths.add("descriptionElements.multilanguageText.language");
652
            propertyPaths.add("descriptionElements.area");
653
            propertyPaths.add("descriptionElements.status");
654
            propertyPaths.add("descriptionElements.modifyingText");
655
            propertyPaths.add("descriptionElementsmodifyingText.language");
656
            propertyPaths.add("descriptionElements.modifiers");
657

    
658
            defaultBeanInitializer.initialize(descriptionBase, propertyPaths);
659
        }
660
        return descriptionBase;
661
    }
662

    
663

    
664
    @Override
665
    public List<Integer> getIndividualAssociationSpecimenIDs(UUID taxonUuid,
666
            Set<Feature> features, Integer pageSize,
667
            Integer pageNumber, List<String> propertyPaths){
668
        Query query = prepareGetDescriptionElementForTaxon(taxonUuid, features, IndividualsAssociation.class, pageSize, pageNumber, "de.associatedSpecimenOrObservation.id");
669
        @SuppressWarnings("unchecked")
670
        List<Integer> results = query.list();
671
        return results;
672
    }
673

    
674
    @Override
675
    public <T extends DescriptionElementBase> List<T> getDescriptionElementForTaxon(
676
            UUID taxonUuid, Set<Feature> features,
677
            Class<T> type, Integer pageSize,
678
            Integer pageNumber, List<String> propertyPaths) {
679

    
680
//        Logger.getLogger("org.hibernate.SQL").setLevel(Level.TRACE);
681

    
682
        Query query = prepareGetDescriptionElementForTaxon(taxonUuid, features, type, pageSize, pageNumber, "de");
683

    
684
        if (logger.isDebugEnabled()){logger.debug(" dao: get list ...");}
685
        @SuppressWarnings("unchecked")
686
        List<T> results = query.list();
687
        if (logger.isDebugEnabled()){logger.debug(" dao: initialize ...");}
688
        defaultBeanInitializer.initializeAll(results, propertyPaths);
689
        if (logger.isDebugEnabled()){logger.debug(" dao: initialize - DONE");}
690

    
691
//        Logger.getLogger("org.hibernate.SQL").setLevel(Level.WARN);
692
        return results;
693
    }
694

    
695
    @Override
696
    public <T extends DescriptionElementBase> long countDescriptionElementForTaxon(
697
            UUID taxonUuid, Set<Feature> features, Class<T> type) {
698

    
699
        Query query = prepareGetDescriptionElementForTaxon(taxonUuid, features, type, null, null, "count(de)");
700

    
701
        return (Long)query.uniqueResult();
702
    }
703

    
704
    private <T extends DescriptionElementBase> Query prepareGetDescriptionElementForTaxon(UUID taxonUuid,
705
            Set<Feature> features, Class<T> type, Integer pageSize, Integer pageNumber, String selectString) {
706

    
707
        String queryString = "SELECT " + selectString + " FROM DescriptionElementBase AS de" +
708
                " LEFT JOIN de.inDescription AS d" +
709
                " LEFT JOIN d.taxon AS t" +
710
                " WHERE d.class = 'TaxonDescription' AND t.uuid = :taxon_uuid ";
711

    
712
        if(type != null){
713
            queryString += " and de.class = :type";
714
        }
715
        if (features != null && features.size() > 0){
716
            queryString += " and de.feature in (:features) ";
717
        }
718
//		System.out.println(queryString);
719
        Query query = getSession().createQuery(queryString);
720

    
721
        query.setParameter("taxon_uuid", taxonUuid);
722
        if(type != null){
723
            query.setParameter("type", type.getSimpleName());
724
        }
725
        if(features != null && features.size() > 0){
726
            query.setParameterList("features", features) ;
727
        }
728

    
729
        if(pageSize != null) {
730
            query.setMaxResults(pageSize);
731
            if(pageNumber != null) {
732
                query.setFirstResult(pageNumber * pageSize);
733
            }
734
        }
735
        return query;
736
    }
737

    
738
    /* (non-Javadoc)
739
     * @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)
740
     */
741
    @Override
742
    public List<Media> listTaxonDescriptionMedia(UUID taxonUuid,
743
            Boolean limitToGalleries, Set<MarkerType> markerTypes,
744
            Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
745

    
746
               AuditEvent auditEvent = getAuditEventFromContext();
747
            if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
748
                String queryString = " SELECT media " +
749
                    getTaxonDescriptionMediaQueryString(
750
                        taxonUuid, limitToGalleries,  markerTypes);
751
                queryString +=
752
                    " GROUP BY media "
753
//	    						" ORDER BY index(media) "  //not functional
754
                    ;
755

    
756
                Query query = getSession().createQuery(queryString);
757

    
758
                setTaxonDescriptionMediaParameters(query, taxonUuid, limitToGalleries, markerTypes);
759

    
760

    
761
//	            addMarkerTypesCriterion(markerTypes, hql);
762

    
763
                setPagingParameter(query, pageSize, pageNumber);
764

    
765
                @SuppressWarnings("unchecked")
766
                List<Media> results = query.list();
767

    
768
                defaultBeanInitializer.initializeAll(results, propertyPaths);
769

    
770
                return results;
771
            } else {
772
                throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid, boolean restrictToGalleries)");
773
            }
774
    }
775

    
776
    @Override
777
    public int countTaxonDescriptionMedia(UUID taxonUuid,
778
            Boolean limitToGalleries, Set<MarkerType> markerTypes) {
779
        AuditEvent auditEvent = getAuditEventFromContext();
780
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
781
            String queryString = " SELECT count(DISTINCT media) " +
782
                getTaxonDescriptionMediaQueryString(
783
                    taxonUuid, limitToGalleries, markerTypes);
784

    
785
            Query query = getSession().createQuery(queryString);
786
            setTaxonDescriptionMediaParameters(query, taxonUuid, limitToGalleries, markerTypes);
787
            return ((Long)query.uniqueResult()).intValue();
788
        }else{
789
            throw new OperationNotSupportedInPriorViewException("countTaxonDescriptionMedia(UUID taxonUuid)");
790
        }
791

    
792
    }
793

    
794
    private void setTaxonDescriptionMediaParameters(Query query, UUID taxonUuid, Boolean limitToGalleries, Set<MarkerType> markerTypes) {
795
        if(taxonUuid != null){
796
            query.setParameter("uuid", taxonUuid);
797
        }
798

    
799
    }
800

    
801
    /**
802
     * @param taxonUuid
803
     * @param restrictToGalleries
804
     * @param markerTypes
805
     * @return
806
     */
807
    private String getTaxonDescriptionMediaQueryString(UUID taxonUuid,
808
            Boolean restrictToGalleries, Set<MarkerType> markerTypes) {
809
        String fromQueryString =
810
            " FROM DescriptionElementBase as deb INNER JOIN " +
811
                " deb.inDescription as td "
812
                + " INNER JOIN td.taxon as t "
813
                + " JOIN deb.media as media "
814
                + " LEFT JOIN td.markers marker ";
815

    
816
        String whereQueryString = " WHERE (1=1) ";
817
        if (taxonUuid != null){
818
            whereQueryString += " AND t.uuid = :uuid ";
819
        }
820
        if (restrictToGalleries){
821
            whereQueryString += " AND td.imageGallery is true ";
822
        }
823
        if (markerTypes != null && !markerTypes.isEmpty()){
824
            whereQueryString += " AND (1=0";
825
            for (MarkerType markerType : markerTypes){
826
                whereQueryString += " OR ( marker.markerType.id = " + markerType.getId() + " AND marker.flag is true)";
827

    
828
            }
829
            whereQueryString += ") ";
830
        }
831

    
832
        return fromQueryString + whereQueryString;
833

    
834
    }
835

    
836
    @SuppressWarnings("unchecked")
837
    @Override
838
    public List<TermDto> listNamedAreasInUse(boolean includeAllParents, Integer pageSize, Integer pageNumber) {
839

    
840
//        Logger.getLogger("org.hibernate.SQL").setLevel(Level.TRACE);
841

    
842
        StringBuilder queryString = new StringBuilder(
843
                "SELECT DISTINCT a.id, a.partOf.id"
844
                + " FROM Distribution AS d JOIN d.area AS a");
845
        Query query = getSession().createQuery(queryString.toString());
846

    
847
        List<Object[]> areasInUse = query.list();
848
        List<Object[]> parentResults = new ArrayList<Object[]>();
849

    
850
        if(!areasInUse.isEmpty()) {
851
            Set<Object> allAreaIds = new HashSet<>(areasInUse.size());
852

    
853
            if(includeAllParents) {
854
                // find all parent nodes
855
                String allAreasQueryStr = "select a.id, a.partOf.id from NamedArea as a";
856
                query = getSession().createQuery(allAreasQueryStr);
857
                List<Object[]> allAreasResult = query.list();
858
                Map<Object, Object> allAreasMap = ArrayUtils.toMap(allAreasResult.toArray());
859

    
860
                Set<Object> parents = new HashSet<>();
861

    
862
                for(Object[] leaf : areasInUse) {
863
                    allAreaIds.add(leaf[0]);
864
                    Object parentId = leaf[1];
865
                    while (parentId != null) {
866
                        if(parents.contains(parentId)) {
867
                            // break if the parent already is in the set
868
                            break;
869
                        }
870
                        parents.add(parentId);
871
                        parentId = allAreasMap.get(parentId);
872
                    }
873
                }
874
                allAreaIds.addAll(parents);
875
            } else {
876
                // only add the ids found so far
877
                for(Object[] leaf : areasInUse) {
878
                    allAreaIds.add(leaf[0]);
879
                }
880
            }
881

    
882

    
883
            // NOTE can't use "select new TermDto(distinct a.uuid, r , a.vocabulary.uuid) since we will get multiple
884
            // rows for a term with multiple representations
885
            String parentAreasQueryStr = TermDto.getTermDtoSelect("NamedArea")
886
                    + "where a.id in (:allAreaIds) order by a.idInVocabulary";
887
            query = getSession().createQuery(parentAreasQueryStr);
888
            query.setParameterList("allAreaIds", allAreaIds);
889
            if(pageSize != null) {
890
                query.setMaxResults(pageSize);
891
                if(pageNumber != null) {
892
                    query.setFirstResult(pageNumber * pageSize);
893
                }
894
            }
895
            parentResults = query.list();
896
        }
897
        List<TermDto> dtoList = TermDto.termDtoListFrom(parentResults);
898

    
899
        return dtoList;
900
    }
901

    
902
}
(1-1/10)