Project

General

Profile

Download (44.6 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.name;
11

    
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Optional;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
21
import org.hibernate.Criteria;
22
import org.hibernate.criterion.Criterion;
23
import org.hibernate.criterion.LogicalExpression;
24
import org.hibernate.criterion.Order;
25
import org.hibernate.criterion.Projections;
26
import org.hibernate.criterion.Restrictions;
27
import org.hibernate.envers.query.AuditEntity;
28
import org.hibernate.envers.query.AuditQuery;
29
import org.hibernate.query.Query;
30
import org.springframework.beans.factory.annotation.Autowired;
31
import org.springframework.beans.factory.annotation.Qualifier;
32
import org.springframework.stereotype.Repository;
33

    
34
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
35
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
36
import eu.etaxonomy.cdm.model.name.HybridRelationship;
37
import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
38
import eu.etaxonomy.cdm.model.name.INonViralName;
39
import eu.etaxonomy.cdm.model.name.IZoologicalName;
40
import eu.etaxonomy.cdm.model.name.NameRelationship;
41
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
42
import eu.etaxonomy.cdm.model.name.Rank;
43
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
44
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
45
import eu.etaxonomy.cdm.model.name.TaxonName;
46
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
47
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
48
import eu.etaxonomy.cdm.model.taxon.Synonym;
49
import eu.etaxonomy.cdm.model.taxon.Taxon;
50
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
51
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
52
import eu.etaxonomy.cdm.model.view.AuditEvent;
53
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
54
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
55
import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
56
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
57
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
58
import eu.etaxonomy.cdm.persistence.dto.TaxonNameParts;
59
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
60
import eu.etaxonomy.cdm.persistence.query.MatchMode;
61
import eu.etaxonomy.cdm.persistence.query.OrderHint;
62

    
63
/**
64
 * @author a.mueller
65
 *
66
 */
67
@Repository
68
@Qualifier("taxonNameDaoHibernateImpl")
69
public class TaxonNameDaoHibernateImpl extends IdentifiableDaoBase<TaxonName> implements ITaxonNameDao {
70

    
71
    private static final Logger logger = LogManager.getLogger(TaxonNameDaoHibernateImpl.class);
72

    
73
    @Autowired
74
    private ITaxonDao taxonDao;
75

    
76
    @Autowired
77

    
78
    private IHomotypicalGroupDao homotypicalGroupDao;
79

    
80
    public TaxonNameDaoHibernateImpl() {
81
        super(TaxonName.class);
82
        indexedClasses = new Class[1];
83
        indexedClasses[0] = TaxonName.class;
84
    }
85

    
86
    @Override
87
    public int countHybridNames(INonViralName name, HybridRelationshipType type) {
88
        AuditEvent auditEvent = getAuditEventFromContext();
89
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
90
            Query<Long> query = null;
91
            if(type == null) {
92
                query = getSession().createQuery("select count(relation) from HybridRelationship relation where relation.relatedFrom = :name", Long.class);
93
            } else {
94
                query = getSession().createQuery("select count(relation) from HybridRelationship relation where relation.relatedFrom = :name and relation.type = :type", Long.class);
95
                query.setParameter("type", type);
96
            }
97
            query.setParameter("name",name);
98
            return query.uniqueResult().intValue();
99
        } else {
100
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(HybridRelationship.class,auditEvent.getRevisionNumber());
101
            query.add(AuditEntity.relatedId("relatedFrom").eq(name.getId()));
102
            query.addProjection(AuditEntity.id().count());
103

    
104
            if(type != null) {
105
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
106
            }
107

    
108
            return ((Long)query.getSingleResult()).intValue();
109
        }
110
    }
111

    
112
    @Override
113
    public long countNames(String queryString) {
114
        checkNotInPriorView("TaxonNameDaoHibernateImpl.countNames(String queryString)");
115
        Criteria criteria = getCriteria(null);
116

    
117
        if (queryString != null) {
118
            criteria.add(Restrictions.ilike("nameCache", queryString));
119
        }
120
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
121

    
122
        return (Long)criteria.uniqueResult();
123
    }
124

    
125
    @Override
126
    public long countNames(String queryString, MatchMode matchMode, List<Criterion> criteria) {
127

    
128
        Criteria crit = getCriteria(type);
129
        if (matchMode == MatchMode.EXACT) {
130
            crit.add(Restrictions.eq("nameCache", matchMode.queryStringFrom(queryString)));
131
        } else {
132
            crit.add(Restrictions.ilike("nameCache", matchMode.queryStringFrom(queryString)));
133
        }
134
        if(criteria != null) {
135
            for (Criterion criterion : criteria) {
136
                crit.add(criterion);
137
            }
138
        }
139

    
140
        crit.setProjection(Projections.projectionList().add(Projections.rowCount()));
141
        return (Long)crit.uniqueResult();
142
    }
143

    
144
    @Override
145
    public long countNames(String genusOrUninomial, String infraGenericEpithet,	String specificEpithet, String infraSpecificEpithet, Rank rank) {
146
        AuditEvent auditEvent = getAuditEventFromContext();
147
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
148
            Criteria criteria = getCriteria(TaxonName.class);
149

    
150
            /**
151
             * Given HHH-2951 - "Restrictions.eq when passed null, should create a NullRestriction"
152
             * We need to convert nulls to NullRestrictions for now
153
             */
154
            if(genusOrUninomial != null) {
155
                criteria.add(Restrictions.eq("genusOrUninomial",genusOrUninomial));
156
            } else {
157
                criteria.add(Restrictions.isNull("genusOrUninomial"));
158
            }
159

    
160
            if(infraGenericEpithet != null) {
161
                criteria.add(Restrictions.eq("infraGenericEpithet", infraGenericEpithet));
162
            } else {
163
                criteria.add(Restrictions.isNull("infraGenericEpithet"));
164
            }
165

    
166
            if(specificEpithet != null) {
167
                criteria.add(Restrictions.eq("specificEpithet", specificEpithet));
168
            } else {
169
                criteria.add(Restrictions.isNull("specificEpithet"));
170
            }
171

    
172
            if(infraSpecificEpithet != null) {
173
                criteria.add(Restrictions.eq("infraSpecificEpithet",infraSpecificEpithet));
174
            } else {
175
                criteria.add(Restrictions.isNull("infraSpecificEpithet"));
176
            }
177

    
178
            if(rank != null) {
179
                criteria.add(Restrictions.eq("rank", rank));
180
            }
181

    
182
            criteria.setProjection(Projections.rowCount());
183
            return (Long)criteria.uniqueResult();
184
        } else {
185
            AuditQuery query = makeAuditQuery(TaxonName.class, auditEvent);
186

    
187
            if(genusOrUninomial != null) {
188
                query.add(AuditEntity.property("genusOrUninomial").eq(genusOrUninomial));
189
            } else {
190
                query.add(AuditEntity.property("genusOrUninomial").isNull());
191
            }
192

    
193
            if(infraGenericEpithet != null) {
194
                query.add(AuditEntity.property("infraGenericEpithet").eq(infraGenericEpithet));
195
            } else {
196
                query.add(AuditEntity.property("infraGenericEpithet").isNull());
197
            }
198

    
199
            if(specificEpithet != null) {
200
                query.add(AuditEntity.property("specificEpithet").eq(specificEpithet));
201
            } else {
202
                query.add(AuditEntity.property("specificEpithet").isNull());
203
            }
204

    
205
            if(infraSpecificEpithet != null) {
206
                query.add(AuditEntity.property("infraSpecificEpithet").eq(infraSpecificEpithet));
207
            } else {
208
                query.add(AuditEntity.property("infraSpecificEpithet").isNull());
209
            }
210

    
211
            if(rank != null) {
212
                query.add(AuditEntity.relatedId("rank").eq(rank.getId()));
213
            }
214

    
215
            query.addProjection(AuditEntity.id().count());
216
            return (Long)query.getSingleResult();
217
        }
218
    }
219

    
220
    @Override
221
    public int countNameRelationships(TaxonName name, NameRelationship.Direction direction, NameRelationshipType type) {
222

    
223
        AuditEvent auditEvent = getAuditEventFromContext();
224
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
225
            Query query = null;
226
            if(type == null) {
227
                query = getSession().createQuery("select count(relation) from NameRelationship relation where relation." + direction +" = :name");
228
            } else {
229
                query = getSession().createQuery("select count(relation) from NameRelationship relation where relation." + direction +" = :name and relation.type = :type");
230
                query.setParameter("type", type);
231
            }
232
            query.setParameter("name",name);
233
            return ((Long)query.uniqueResult()).intValue();
234
        } else {
235
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(NameRelationship.class,auditEvent.getRevisionNumber());
236
            query.add(AuditEntity.relatedId(direction.toString()).eq(name.getId()));
237
            query.addProjection(AuditEntity.id().count());
238

    
239
            if(type != null) {
240
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
241
            }
242

    
243
            return ((Long)query.getSingleResult()).intValue();
244
        }
245
    }
246

    
247

    
248
    @Override
249
    public long countTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status) {
250
        checkNotInPriorView("countTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status)");
251
        Query<Long> query = null;
252
        if(status == null) {
253
            query = getSession().createQuery("select count(designation) from TypeDesignationBase designation join designation.typifiedNames name where name = :name", Long.class);
254
        } else {
255
            query = getSession().createQuery("select count(designation) from TypeDesignationBase designation join designation.typifiedNames name where name = :name and designation.typeStatus = :status", Long.class);
256
            query.setParameter("status", status);
257
        }
258
        query.setParameter("name",name);
259
        return query.uniqueResult();
260
    }
261

    
262
    @Override
263
    public List<HybridRelationship> getHybridNames(INonViralName name, HybridRelationshipType type,
264
            Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
265
        AuditEvent auditEvent = getAuditEventFromContext();
266
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
267
            Criteria criteria = getSession().createCriteria(HybridRelationship.class);
268
            criteria.add(Restrictions.eq("relatedFrom", name));
269
            if(type != null) {
270
                criteria.add(Restrictions.eq("type", type));
271
            }
272

    
273
            addPageSizeAndNumber(criteria, pageSize, pageNumber);
274
            addOrder(criteria, orderHints);
275

    
276
            @SuppressWarnings("unchecked")
277
            List<HybridRelationship> results = criteria.list();
278
            defaultBeanInitializer.initializeAll(results, propertyPaths);
279
            return results;
280
        } else {
281
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(HybridRelationship.class,auditEvent.getRevisionNumber());
282
            query.add(AuditEntity.relatedId("relatedFrom").eq(name.getId()));
283

    
284
            if(type != null) {
285
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
286
            }
287

    
288
            if(pageSize != null) {
289
                query.setMaxResults(pageSize);
290
                if(pageNumber != null) {
291
                    query.setFirstResult(pageNumber * pageSize);
292
                } else {
293
                    query.setFirstResult(0);
294
                }
295
            }
296

    
297
            @SuppressWarnings("unchecked")
298
            List<HybridRelationship> results =  query.getResultList();
299
            defaultBeanInitializer.initializeAll(results, propertyPaths);
300
            return results;
301
        }
302
    }
303

    
304
    @Override
305
    public List<NameRelationship> getNameRelationships(TaxonName name, NameRelationship.Direction direction,
306
            NameRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
307
            List<String> propertyPaths) {
308

    
309
        AuditEvent auditEvent = getAuditEventFromContext();
310
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
311
            Criteria criteria = getSession().createCriteria(NameRelationship.class);
312
            if (name != null || direction != null){
313
                criteria.add(Restrictions.eq(direction.toString(), name));
314
            }
315
            if(type != null) {
316
                criteria.add(Restrictions.eq("type", type));
317
            }
318

    
319
            if(pageSize != null) {
320
                criteria.setMaxResults(pageSize);
321
                if(pageNumber != null) {
322
                    criteria.setFirstResult(pageNumber * pageSize);
323
                } else {
324
                    criteria.setFirstResult(0);
325
                }
326
            }
327
            addOrder(criteria, orderHints);
328

    
329
            @SuppressWarnings("unchecked")
330
            List<NameRelationship> results = criteria.list();
331
            defaultBeanInitializer.initializeAll(results, propertyPaths);
332
            return results;
333
        } else {
334
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(NameRelationship.class,auditEvent.getRevisionNumber());
335
            query.add(AuditEntity.relatedId(direction.toString()).eq(name.getId()));
336

    
337
            if(type != null) {
338
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
339
            }
340

    
341
            if(pageSize != null) {
342
                query.setMaxResults(pageSize);
343
                if(pageNumber != null) {
344
                    query.setFirstResult(pageNumber * pageSize);
345
                } else {
346
                    query.setFirstResult(0);
347
                }
348
            }
349

    
350
            @SuppressWarnings("unchecked")
351
            List<NameRelationship> results = query.getResultList();
352
            defaultBeanInitializer.initializeAll(results, propertyPaths);
353
            return results;
354
        }
355
    }
356

    
357
    @Override
358
    public List<TypeDesignationBase> getTypeDesignations(TaxonName name, TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber,	List<String> propertyPaths){
359
        return getTypeDesignations(name, null, status, pageSize, pageNumber, propertyPaths);
360
    }
361

    
362
    @Override
363
    public List<Integer> getTypeSpecimenIdsForTaxonName(TaxonName name,
364
            TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber){
365
        Query<Integer> query = getTypeDesignationQuery("designation.typeSpecimen.id", name, SpecimenTypeDesignation.class, status);
366

    
367
        addPageSizeAndNumber(query, pageSize, pageNumber);
368
        List<Integer> result = query.list();
369
        return result;
370
    }
371

    
372
    @Override
373
    public <T extends TypeDesignationBase> List<T> getTypeDesignations(TaxonName name,
374
                Class<T> type,
375
                TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber,
376
                List<String> propertyPaths){
377
        checkNotInPriorView("getTypeDesignations(TaxonName name,TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber,	List<String> propertyPaths)");
378

    
379
        Query<T> query = getTypeDesignationQuery("designation", name, type, status);
380

    
381
        addPageSizeAndNumber(query, pageSize, pageNumber);
382
        List<T> result = defaultBeanInitializer.initializeAll(query.list(), propertyPaths);
383
        return result;
384
    }
385

    
386
    private <T extends TypeDesignationBase> Query getTypeDesignationQuery(String select, TaxonName name,
387
            Class<T> type, TypeDesignationStatusBase status){
388

    
389
        Query<?> query = null;
390
        String queryString = "select "+select+" from TypeDesignationBase designation join designation.typifiedNames name where name = :name";
391

    
392
        if(status != null) {
393
            queryString +=  " and designation.typeStatus = :status";
394
        }
395
        if(type != null){
396
            queryString +=  " and designation.class = :type";
397
        }
398

    
399
        query = getSession().createQuery(queryString);
400

    
401
        if(status != null) {
402
            query.setParameter("status", status);
403
        }
404
        if(type != null){
405
            query.setParameter("type", type.getSimpleName());
406
        }
407

    
408
        query.setParameter("name",name);
409
        return query;
410
    }
411

    
412
    public List<TaxonName> searchNames(String queryString, MatchMode matchMode, Integer pageSize, Integer pageNumber) {
413
        checkNotInPriorView("TaxonNameDaoHibernateImpl.searchNames(String queryString, Integer pageSize, Integer pageNumber)");
414
        Criteria criteria = getSession().createCriteria(TaxonName.class);
415

    
416
        if (queryString != null) {
417
            criteria.add(Restrictions.ilike("nameCache", queryString));
418
        }
419
        if(pageSize != null) {
420
            criteria.setMaxResults(pageSize);
421
            if(pageNumber != null) {
422
                criteria.setFirstResult(pageNumber * pageSize);
423
            } else {
424
                criteria.setFirstResult(0);
425
            }
426
        }
427
        @SuppressWarnings("unchecked")
428
        List<TaxonName> results = criteria.list();
429
        return results;
430
    }
431

    
432

    
433
    @Override
434
    public List<TaxonName> searchNames(String queryString, Integer pageSize, Integer pageNumber) {
435
        return searchNames(queryString, MatchMode.BEGINNING, pageSize, pageNumber);
436
    }
437

    
438

    
439
    @Override
440
    public List<TaxonName> searchNames(String genusOrUninomial,String infraGenericEpithet, String specificEpithet,	String infraSpecificEpithet, Rank rank, Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,
441
            List<String> propertyPaths) {
442
        AuditEvent auditEvent = getAuditEventFromContext();
443
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
444
            Criteria criteria = getSession().createCriteria(TaxonName.class);
445

    
446
            /**
447
             * Given HHH-2951 - "Restrictions.eq when passed null, should create a NullRestriction"
448
             * We need to convert nulls to NullRestrictions for now
449
             */
450
            if(genusOrUninomial != null) {
451
                criteria.add(Restrictions.eq("genusOrUninomial",genusOrUninomial));
452
            } else {
453
                criteria.add(Restrictions.isNull("genusOrUninomial"));
454
            }
455

    
456
            if(infraGenericEpithet != null) {
457
                criteria.add(Restrictions.eq("infraGenericEpithet", infraGenericEpithet));
458
            } else {
459
                criteria.add(Restrictions.isNull("infraGenericEpithet"));
460
            }
461

    
462
            if(specificEpithet != null) {
463
                criteria.add(Restrictions.eq("specificEpithet", specificEpithet));
464
            } else {
465
                criteria.add(Restrictions.isNull("specificEpithet"));
466
            }
467

    
468
            if(infraSpecificEpithet != null) {
469
                criteria.add(Restrictions.eq("infraSpecificEpithet",infraSpecificEpithet));
470
            } else {
471
                criteria.add(Restrictions.isNull("infraSpecificEpithet"));
472
            }
473

    
474
            if(rank != null) {
475
                criteria.add(Restrictions.eq("rank", rank));
476
            }
477

    
478
            if(pageSize != null) {
479
                criteria.setMaxResults(pageSize);
480
                if(pageNumber != null) {
481
                    criteria.setFirstResult(pageNumber * pageSize);
482
                } else {
483
                    criteria.setFirstResult(0);
484
                }
485
            }
486

    
487
            addOrder(criteria, orderHints);
488

    
489
            @SuppressWarnings("unchecked")
490
            List<TaxonName> results = criteria.list();
491
            defaultBeanInitializer.initializeAll(results, propertyPaths);
492
            return results;
493
        } else {
494
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonName.class,auditEvent.getRevisionNumber());
495

    
496
            if(genusOrUninomial != null) {
497
                query.add(AuditEntity.property("genusOrUninomial").eq(genusOrUninomial));
498
            } else {
499
                query.add(AuditEntity.property("genusOrUninomial").isNull());
500
            }
501

    
502
            if(infraGenericEpithet != null) {
503
                query.add(AuditEntity.property("infraGenericEpithet").eq(infraGenericEpithet));
504
            } else {
505
                query.add(AuditEntity.property("infraGenericEpithet").isNull());
506
            }
507

    
508
            if(specificEpithet != null) {
509
                query.add(AuditEntity.property("specificEpithet").eq(specificEpithet));
510
            } else {
511
                query.add(AuditEntity.property("specificEpithet").isNull());
512
            }
513

    
514
            if(infraSpecificEpithet != null) {
515
                query.add(AuditEntity.property("infraSpecificEpithet").eq(infraSpecificEpithet));
516
            } else {
517
                query.add(AuditEntity.property("infraSpecificEpithet").isNull());
518
            }
519

    
520
            if(rank != null) {
521
                query.add(AuditEntity.relatedId("rank").eq(rank.getId()));
522
            }
523

    
524
            if(pageSize != null) {
525
                query.setMaxResults(pageSize);
526
                if(pageNumber != null) {
527
                    query.setFirstResult(pageNumber * pageSize);
528
                } else {
529
                    query.setFirstResult(0);
530
                }
531
            }
532

    
533
            @SuppressWarnings("unchecked")
534
            List<TaxonName> results = query.getResultList();
535
            defaultBeanInitializer.initializeAll(results, propertyPaths);
536
            return results;
537
        }
538
    }
539

    
540
    @Override
541
    public List<TaxonName> findByName(boolean doIncludeAuthors,
542
            String queryString, MatchMode matchmode, Integer pageSize,
543
            Integer pageNumber, List<Criterion> criteria, List<String> propertyPaths) {
544

    
545
        Criteria crit = getSession().createCriteria(type);
546
        Criterion nameCacheLike;
547
        if (matchmode == MatchMode.EXACT) {
548
            nameCacheLike = Restrictions.eq("nameCache", matchmode.queryStringFrom(queryString));
549
        } else {
550
            nameCacheLike = Restrictions.ilike("nameCache", matchmode.queryStringFrom(queryString));
551
        }
552
        Criterion notNull = Restrictions.isNotNull("nameCache");
553
        LogicalExpression nameCacheExpression = Restrictions.and(notNull, nameCacheLike);
554

    
555
        Criterion titleCacheLike;
556
        if (matchmode == MatchMode.EXACT) {
557
            titleCacheLike = Restrictions.eq("titleCache", matchmode.queryStringFrom(queryString));
558
        } else {
559
            titleCacheLike =Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString));
560
        }
561
        Criterion isNull = Restrictions.isNull("nameCache");
562
        LogicalExpression titleCacheExpression = Restrictions.and(isNull, titleCacheLike);
563

    
564
        LogicalExpression orExpression = Restrictions.or(titleCacheExpression, nameCacheExpression);
565

    
566
        Criterion finalCriterion = doIncludeAuthors ? titleCacheLike : orExpression;
567

    
568
        crit.add(finalCriterion);
569
        if(criteria != null){
570
            for (Criterion criterion : criteria) {
571
                crit.add(criterion);
572
            }
573
        }
574
        crit.addOrder(Order.asc("nameCache"));
575

    
576
        if(pageSize != null) {
577
            crit.setMaxResults(pageSize);
578
            if(pageNumber != null) {
579
                crit.setFirstResult(pageNumber * pageSize);
580
            }
581
        }
582

    
583
        @SuppressWarnings("unchecked")
584
        List<TaxonName> results = crit.list();
585
        defaultBeanInitializer.initializeAll(results, propertyPaths);
586

    
587
        return results;
588
    }
589

    
590
    @Override
591
    public List<TaxonName> findByFullTitle(String queryString,
592
            MatchMode matchmode, Integer pageSize, Integer pageNumber, List<Criterion> criteria, List<String> propertyPaths) {
593

    
594
        Criteria crit = getSession().createCriteria(type);
595
        if (matchmode == null){
596
            matchmode = MatchMode.LIKE;
597
        }
598
        if (matchmode == MatchMode.EXACT) {
599
            crit.add(Restrictions.eq("fullTitleCache", matchmode.queryStringFrom(queryString)));
600
        } else {
601
            crit.add(Restrictions.ilike("fullTitleCache", matchmode.queryStringFrom(queryString)));
602
        }
603
        if(criteria != null){
604
            for (Criterion criterion : criteria) {
605
                crit.add(criterion);
606
            }
607
        }
608
        crit.addOrder(Order.asc("fullTitleCache"));
609

    
610
        if(pageSize != null) {
611
            crit.setMaxResults(pageSize);
612
            if(pageNumber != null) {
613
                crit.setFirstResult(pageNumber * pageSize);
614
            }
615
        }
616

    
617
        @SuppressWarnings("unchecked")
618
        List<TaxonName> results = crit.list();
619
        defaultBeanInitializer.initializeAll(results, propertyPaths);
620

    
621
        return results;
622
    }
623

    
624
    @Override
625
    public List<TaxonName> findByTitle(String queryString,
626
            MatchMode matchmode, Integer pageSize, Integer pageNumber, List<Criterion> criteria, List<String> propertyPaths) {
627

    
628
        Criteria crit = getSession().createCriteria(type);
629
        if (matchmode == MatchMode.EXACT) {
630
            crit.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(queryString)));
631
        } else {
632
            crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
633
        }
634
        if(criteria != null){
635
            for (Criterion criterion : criteria) {
636
                crit.add(criterion);
637
            }
638
        }
639
        crit.addOrder(Order.asc("titleCache"));
640

    
641
        if(pageSize != null) {
642
            crit.setMaxResults(pageSize);
643
            if(pageNumber != null) {
644
                crit.setFirstResult(pageNumber * pageSize);
645
            }
646
        }
647

    
648
        @SuppressWarnings("unchecked")
649
        List<TaxonName> results = crit.list();
650
        defaultBeanInitializer.initializeAll(results, propertyPaths);
651

    
652
        return results;
653
    }
654

    
655

    
656
    @Override
657
    public TaxonName findByUuid(UUID uuid, List<Criterion> criteria, List<String> propertyPaths) {
658

    
659
        Criteria crit = getSession().createCriteria(type);
660

    
661
        if (uuid != null) {
662
            crit.add(Restrictions.eq("uuid", uuid));
663
        } else {
664
            logger.warn("UUID is NULL");
665
            return null;
666
        }
667
        if(criteria != null){
668
            for (Criterion criterion : criteria) {
669
                crit.add(criterion);
670
            }
671
        }
672
        crit.addOrder(Order.asc("uuid"));
673

    
674
        @SuppressWarnings("unchecked")
675
        List<TaxonName> results = crit.list();
676
        if (results.size() == 1) {
677
            defaultBeanInitializer.initializeAll(results, propertyPaths);
678
            TaxonName taxonName = results.iterator().next();
679
            return taxonName;
680
        } else if (results.size() > 1) {
681
            logger.error("Multiple results for UUID: " + uuid);
682
        } else if (results.size() == 0) {
683
            logger.info("No results for UUID: " + uuid);
684
        }
685

    
686
        return null;
687
    }
688

    
689

    
690
    @Override
691
    public <S extends TaxonName> List<S> list(Class<S> type, List<Restriction<?>> restrictions, Integer limit,
692
            Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
693
        // TODO Auto-generated method stub
694
        return list(type, restrictions, limit, start, orderHints, propertyPaths, INCLUDE_UNPUBLISHED);
695
    }
696

    
697
    @Override
698
    public <S extends TaxonName> List<S> list(Class<S> type, List<Restriction<?>> restrictions, Integer limit,
699
            Integer start, List<OrderHint> orderHints, List<String> propertyPaths, boolean includePublished) {
700
        Criteria criteria = createCriteria(type, restrictions, false);
701

    
702
        if(!includePublished){
703
            criteria.add(Restrictions.eq("taxonBases.publish", true));
704
        }
705

    
706
        addLimitAndStart(criteria, limit, start);
707
        addOrder(criteria, orderHints);
708

    
709
        @SuppressWarnings("unchecked")
710
        List<S> result = criteria.list();
711
        defaultBeanInitializer.initializeAll(result, propertyPaths);
712
        return result;
713
    }
714

    
715
    @Override
716
    public long count(Class<? extends TaxonName> type, List<Restriction<?>> restrictions) {
717
        return count(type, restrictions, INCLUDE_UNPUBLISHED);
718
    }
719

    
720

    
721
    @Override
722
    public long count(Class<? extends TaxonName> type, List<Restriction<?>> restrictions, boolean includePublished) {
723

    
724
        Criteria criteria = createCriteria(type, restrictions, false);
725
        if(!includePublished){
726
            criteria.add(Restrictions.eq("taxonBases.publish", true));
727
        }
728
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
729
        return (Long) criteria.uniqueResult();
730
    }
731

    
732
    @Override
733
    public Integer countByName(String queryString, MatchMode matchmode, List<Criterion> criteria) {
734
        //TODO improve performance
735
        boolean includeAuthors = false;
736
        List<TaxonName> results = findByName(
737
                includeAuthors,queryString, matchmode, null, null, criteria, null);
738
        return results.size();
739

    
740
    }
741

    
742
    @Override
743
    public List<UuidAndTitleCache> getUuidAndTitleCacheOfNames(Integer limit, String pattern) {
744
        String queryString = "SELECT uuid, id, fullTitleCache FROM TaxonName LIMIT " + limit;
745

    
746
        @SuppressWarnings("unchecked")
747
        List<Object[]> result = getSession().createSQLQuery(queryString).list();
748

    
749
        if(result.size() == 0){
750
            return null;
751
        }else{
752
            List<UuidAndTitleCache> list = new ArrayList<>(result.size());
753

    
754
            for (Object object : result){
755

    
756
                Object[] objectArray = (Object[]) object;
757

    
758
                UUID uuid = UUID.fromString((String) objectArray[0]);
759
                Integer id = (Integer) objectArray[1];
760
                String titleCache = (String) objectArray[2];
761

    
762
                list.add(new UuidAndTitleCache(type, uuid, id, titleCache));
763
            }
764

    
765
            return list;
766
        }
767
    }
768

    
769
    @Override
770
    public long countByName(Class<TaxonName> clazz,String queryString, MatchMode matchmode, List<Criterion> criteria) {
771
        return super.countByParam(clazz, "nameCache", queryString, matchmode, criteria);
772
    }
773

    
774
    @Override
775
    public long countByFullTitle(Class<TaxonName> clazz,String queryString, MatchMode matchmode, List<Criterion> criteria) {
776
        return super.countByParam(clazz, "fullTitleCache", queryString, matchmode, criteria);
777
    }
778

    
779
    @Override
780
    public List<TaxonName> findByName(Class<TaxonName> clazz,	String queryString, MatchMode matchmode, List<Criterion> criteria,Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,	List<String> propertyPaths) {
781
        return super.findByParam(clazz, "nameCache", queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
782
    }
783

    
784
    @Override
785
    public UUID delete (TaxonName persistentObject){
786
        @SuppressWarnings("rawtypes")
787
        Set<TaxonBase> taxonBases = persistentObject.getTaxonBases();
788

    
789
        getSession().saveOrUpdate(persistentObject);
790
        UUID homotypicalGroupUUID = persistentObject.getHomotypicalGroup().getUuid();
791

    
792

    
793
        for (TaxonBase<?> taxonBase: taxonBases){
794
            taxonDao.delete(taxonBase);
795
        }
796
        HomotypicalGroup homotypicalGroup = homotypicalGroupDao.load(homotypicalGroupUUID);
797
        homotypicalGroup = HibernateProxyHelper.deproxy(homotypicalGroup);
798

    
799
        if (homotypicalGroup != null){
800
            if (homotypicalGroup.getTypifiedNames().contains(persistentObject)){
801
                homotypicalGroup.getTypifiedNames().remove(persistentObject);
802
                homotypicalGroupDao.saveOrUpdate(homotypicalGroup);
803
            }
804
        }
805

    
806
        getSession().delete(persistentObject);
807
        if (homotypicalGroup.getTypifiedNames().isEmpty()){
808
            homotypicalGroupDao.delete(homotypicalGroup);
809
        }
810
        return persistentObject.getUuid();
811
    }
812

    
813

    
814
    @Override
815
    public IZoologicalName findZoologicalNameByUUID(UUID uuid){
816
        Criteria criteria = getSession().createCriteria(type);
817
        if (uuid != null) {
818
            criteria.add(Restrictions.eq("uuid", uuid));
819
        } else {
820
            logger.warn("UUID is NULL");
821
            return null;
822
        }
823

    
824
        @SuppressWarnings("unchecked")
825
        List<TaxonName> results = criteria.list();
826
        if (results.size() == 1) {
827
            defaultBeanInitializer.initializeAll(results, null);
828
            TaxonName taxonName = results.iterator().next();
829
            if (taxonName.isZoological()) {
830
                IZoologicalName zoologicalName = taxonName;
831
                return zoologicalName;
832
            } else {
833
                logger.warn("This UUID (" + uuid + ") does not belong to a ZoologicalName. It belongs to: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
834
            }
835
        } else if (results.size() > 1) {
836
            logger.error("Multiple results for UUID: " + uuid);
837
        } else if (results.size() == 0) {
838
            logger.info("No results for UUID: " + uuid);
839
        }
840
        return null;
841
    }
842

    
843
    @Override
844
    public List<HashMap<String,String>> getNameRecords(){
845
    	String sql= "SELECT"
846
    			+ "  (SELECT famName.namecache FROM TaxonNode famNode"
847
    			+ "  LEFT OUTER JOIN TaxonBase famTax ON famNode.taxon_id = famTax.id"
848
    			+ " LEFT OUTER JOIN TaxonName famName ON famTax.name_id = famName.id"
849
    			+ " WHERE famName.rank_id = 795 AND famNode.treeIndex = SUBSTRING(tn.treeIndex, 1, length(famNode.treeIndex))"
850
    			+ "	) as famName, "
851
    			+ " (SELECT famName.namecache FROM TaxonNode famNode "
852
    			+ " LEFT OUTER JOIN TaxonBase famTax ON famNode.taxon_id = famTax.id "
853
    			+ " LEFT OUTER JOIN TaxonName famName ON famTax.name_id = famName.id "
854
    			+ " WHERE famName.rank_id = 795 AND famNode.treeIndex = SUBSTRING(tnAcc.treeIndex, 1, length(famNode.treeIndex))"
855
    			+ "	) as accFamName,tb.DTYPE, tb.id as TaxonID ,tb.titleCache taxonTitle,  tnb.rank_id as RankID, tnb.id as NameID,"
856
    			+ " tnb.namecache as name, tnb.titleCache as nameAuthor, tnb.fullTitleCache nameAndNomRef,"
857
    			+ "	r.titleCache as nomRef, r.abbrevTitle nomRefAbbrevTitle, r.title nomRefTitle, r.datepublished_start nomRefPublishedStart, r.datepublished_end nomRefPublishedEnd, r.pages nomRefPages, inRef.abbrevTitle inRefAbbrevTitle,tnb.nomenclaturalmicroreference as detail,"
858
    			+ "	nameType.namecache nameType, nameType.titleCache nameTypeAuthor, nameType.fullTitleCache nameTypeFullTitle, nameTypeRef.titleCache nameTypeRef, "
859
    			+ " inRef.seriespart as inRefSeries, inRef.datepublished_start inRefPublishedStart, inRef.datepublished_end inRefPublishedEnd, inRef.volume as inRefVolume"
860
    			+ " FROM TaxonBase tb"
861
    			+ " LEFT OUTER JOIN TaxonName tnb ON tb.name_id = tnb.id"
862
    			+ "	LEFT OUTER JOIN OriginalSourceBase nosb ON tnb.id = nosb.sourcedName_id"
863
    			+ " LEFT OUTER JOIN Reference r ON nosb.citation_id = r.id"
864
                + "	LEFT OUTER JOIN TaxonNode tn ON tn.taxon_id = tb.id"
865
    			+ "	LEFT OUTER JOIN TaxonName_TypeDesignationBase typeMN ON typeMN.TaxonName_id = tnb.id"
866
    			+ " LEFT OUTER JOIN TypeDesignationBase tdb ON tdb.id = typeMN.typedesignations_id"
867
    			+ "	LEFT OUTER JOIN TaxonName nameType ON tdb.typename_id = nameType.id"
868
    			+ " LEFT OUTER JOIN OriginalSourceBase nameTypeOsb ON nameType.id = nameTypeOsb.sourcedName_id"
869
    			+ "	LEFT OUTER JOIN Reference nameTypeRef ON nameTypeOsb.citation_id = nameTypeRef.id"
870
                + "		LEFT OUTER JOIN Reference inRef ON inRef.id = r.inreference_id"
871
    			+ "	LEFT OUTER JOIN TaxonBase accT ON accT.id = tb.acceptedTaxon_id"
872
    			+ "		LEFT OUTER JOIN TaxonNode tnAcc ON tnAcc.taxon_id = accT.id"
873
    			+ "	ORDER BY DTYPE, famName, accFamName,  tnb.rank_id ,tb.titleCache";
874

    
875
    	String hqlQueryStringFrom = "FROM TaxonBase taxonBase "
876
    	        + " LEFT OUTER JOIN taxonBase.name as tnb "
877
    	        + " LEFT OUTER JOIN tnb.nomenclaturalSource as nomSource "
878
    	        + " LEFT OUTER JOIN nomSource.citation as nomRef "
879
                + " LEFT OUTER JOIN taxonBase.taxonNodes as node "
880
    	        + " LEFT OUTER JOIN tnb.typeDesignations as type "
881
    	        + " LEFT OUTER JOIN type.typifiedNames as nameType "
882
    	        + " LEFT OUTER JOIN nameType.nomenclaturalSource as nameTypeSource "
883
    	        + " LEFT OUTER JOIN nameTypeSource.citation as nameTypeRef "
884
                + " LEFT OUTER JOIN nomRef.inReference as inRef "
885
    	        + " LEFT OUTER JOIN taxonBase.acceptedTaxon as accTaxon "
886
    	        + " LEFT OUTER JOIN accTaxon.taxonNodes as accTaxonNodes";
887

    
888
    	Query hqlQuery = getSession().createQuery(hqlQueryStringFrom);
889
    	List<?> hqlResult = hqlQuery.list();
890

    
891
		List<HashMap<String,String>> nameRecords = new ArrayList<>();
892
		HashMap<String,String> nameRecord = new HashMap<>();
893
		TaxonNode familyNode = null;
894
		for(Object object : hqlResult){
895
			Object[] row = (Object[])object;
896
			nameRecord = new HashMap<>();
897
			TaxonBase<?> taxonBase = (TaxonBase<?>)row[0];
898
			Taxon accTaxon = null;
899
			if (taxonBase instanceof Taxon){
900
			    accTaxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
901
			} else{
902
			    nameRecord.put("famName", "");
903
			    Synonym syn = HibernateProxyHelper.deproxy(taxonBase, Synonym.class);
904
			    accTaxon = syn.getAcceptedTaxon();
905
			}
906
			Set<TaxonNode> nodes = accTaxon.getTaxonNodes();
907
            if (nodes.size() == 1){
908
                TaxonNode node = nodes.iterator().next();
909
                familyNode = node.getAncestorOfRank(Rank.FAMILY());
910
            }
911

    
912
            nameRecord.put("famName",familyNode.getTaxon().getName().getNameCache());
913
            nameRecord.put("accFamName","");
914

    
915
			//nameRecord.put("famName",(String)row[0]);
916

    
917
			nameRecord.put("accFamName",(String)row[1]);
918

    
919
			nameRecord.put("DTYPE",(String)row[2]);
920
			nameRecord.put("TaxonID",String.valueOf(row[3]));
921
			nameRecord.put("taxonTitle",(String)row[4]);
922
            nameRecord.put("RankID",String.valueOf(row[5]));
923
            nameRecord.put("NameID",String.valueOf(row[6]));
924
            nameRecord.put("name",(String)row[7]);
925
            nameRecord.put("nameAuthor",(String)row[8]);
926
            nameRecord.put("nameAndNomRef",(String)row[9]);
927
            nameRecord.put("nomRef",(String)row[10]);
928
            nameRecord.put("nomRefAbbrevTitle",(String)row[11]);
929
            nameRecord.put("nomRefTitle",(String)row[12]);
930
            nameRecord.put("nomRefPublishedStart",(String)row[13]);
931
            nameRecord.put("nomRefPublishedEnd",(String)row[14]);
932
            nameRecord.put("nomRefPages",(String)row[15]);
933
            nameRecord.put("inRefAbbrevTitle",(String)row[16]);
934
            nameRecord.put("detail",(String)row[17]);
935
            nameRecord.put("nameType",(String)row[18]);
936
            nameRecord.put("nameTypeAuthor",(String)row[19]);
937
            nameRecord.put("nameTypeFullTitle",(String)row[20]);
938
            nameRecord.put("nameTypeRef",(String)row[21]);
939
            nameRecord.put("inRefSeries",(String)row[22]);
940
            nameRecord.put("inRefPublishedStart",(String)row[23]);
941
            nameRecord.put("inRefPublishedEnd",(String)row[24]);
942
            nameRecord.put("inRefVolume",(String)row[25]);
943
            nameRecords.add(nameRecord);
944
	   }
945

    
946
		return nameRecords;
947
    }
948

    
949
    @Override
950
    public List<TaxonNameParts> findTaxonNameParts(Optional<String> genusOrUninomial,
951
            Optional<String> infraGenericEpithet, Optional<String> specificEpithet,
952
            Optional<String> infraSpecificEpithet, Rank rank, Collection<UUID> excludedNamesUuids, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
953

    
954
        StringBuilder hql = prepareFindTaxonNameParts(false, genusOrUninomial, infraGenericEpithet,
955
                specificEpithet, infraSpecificEpithet, rank, excludedNamesUuids);
956
        addOrder(hql, "n", orderHints);
957
        Query<TaxonNameParts> query = getSession().createQuery(hql.toString(), TaxonNameParts.class);
958
        if(rank != null){
959
            query.setParameter("rank", rank);
960
        }
961
        if(excludedNamesUuids != null && excludedNamesUuids.size() > 0){
962
            query.setParameterList("excludedNamesUuids", excludedNamesUuids);
963
        }
964
        addPageSizeAndNumber(query, pageSize, pageIndex);
965
        List<TaxonNameParts> result = query.list();
966
        return result;
967
    }
968

    
969
    @Override
970
    public long countTaxonNameParts(Optional<String> genusOrUninomial, Optional<String> infraGenericEpithet,
971
            Optional<String> specificEpithet, Optional<String> infraSpecificEpithet, Rank rank, Collection<UUID> excludedNamesUUIDs) {
972

    
973
        StringBuilder hql = prepareFindTaxonNameParts(true, genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet, rank, excludedNamesUUIDs);
974
        Query<Long> query = getSession().createQuery(hql.toString(), Long.class);
975
        if(rank != null){
976
            query.setParameter("rank", rank);
977
        }
978
        if(excludedNamesUUIDs != null && excludedNamesUUIDs.size() > 0){
979
            query.setParameterList("excludedNamesUuids", excludedNamesUUIDs);
980
        }
981

    
982
        return query.uniqueResult();
983
    }
984

    
985
    private StringBuilder prepareFindTaxonNameParts(boolean doCount, Optional<String> genusOrUninomial,
986
            Optional<String> infraGenericEpithet, Optional<String> specificEpithet,
987
            Optional<String> infraSpecificEpithet, Rank rank, Collection<UUID> excludedNamesUuids) {
988

    
989
        StringBuilder hql = new StringBuilder();
990
        if(doCount){
991
            hql.append("select count(n.id) ");
992
        } else {
993
            hql.append("select new eu.etaxonomy.cdm.persistence.dto.TaxonNameParts(n.id, n.uuid, n.rank, n.genusOrUninomial, n.infraGenericEpithet, n.specificEpithet, n.infraSpecificEpithet) ");
994
        }
995
        hql.append("from TaxonName n ");
996
        hql.append("where 1 = 1 ");
997

    
998
        if(rank != null){
999
            hql.append("and n.rank = :rank ");
1000
        }
1001
        if(excludedNamesUuids != null && excludedNamesUuids.size() > 0){
1002
            hql.append("and n.uuid not in ( :excludedNamesUuids ) ");
1003
        }
1004

    
1005
        addFieldPredicate(hql, "n.genusOrUninomial", genusOrUninomial);
1006
        addFieldPredicate(hql, "n.infraGenericEpithet", infraGenericEpithet);
1007
        addFieldPredicate(hql, "n.specificEpithet", specificEpithet);
1008
        addFieldPredicate(hql, "n.infraSpecificEpithet", infraSpecificEpithet);
1009

    
1010
        return hql;
1011
    }
1012

    
1013
    @Override
1014
    public long countNameRelationships(Set<NameRelationshipType> types) {
1015
        Criteria criteria = getSession().createCriteria(NameRelationship.class);
1016

    
1017
        if (types != null) {
1018
            if (types.isEmpty()){
1019
                return 0l;
1020
            }else{
1021
                criteria.add(Restrictions.in("type", types) );
1022
            }
1023
        }
1024
        //count
1025
        criteria.setProjection(Projections.rowCount());
1026
        long result = (Long)criteria.uniqueResult();
1027

    
1028
        return result;
1029
    }
1030

    
1031
    @Override
1032
    public List<NameRelationship> getNameRelationships(Set<NameRelationshipType> types,
1033
            Integer pageSize, Integer pageNumber,
1034
            List<OrderHint> orderHints, List<String> propertyPaths) {
1035

    
1036
        Criteria criteria = getCriteria(NameRelationship.class);
1037
        if (types != null) {
1038
            if (types.isEmpty()){
1039
                return new ArrayList<>();
1040
            }else{
1041
                criteria.add(Restrictions.in("type", types) );
1042
            }
1043
        }
1044
        addOrder(criteria,orderHints);
1045
        addPageSizeAndNumber(criteria, pageSize, pageNumber);
1046

    
1047
        @SuppressWarnings("unchecked")
1048
        List<NameRelationship> results = criteria.list();
1049
        defaultBeanInitializer.initializeAll(results, propertyPaths);
1050

    
1051
        return results;
1052
    }
1053

    
1054
    @Override
1055
    public long countHybridRelationships(Set<HybridRelationshipType> types) {
1056
        Criteria criteria = getSession().createCriteria(HybridRelationship.class);
1057

    
1058
        if (types != null) {
1059
            if (types.isEmpty()){
1060
                return 0l;
1061
            }else{
1062
                criteria.add(Restrictions.in("type", types) );
1063
            }
1064
        }
1065
        //count
1066
        criteria.setProjection(Projections.rowCount());
1067
        long result = (Long)criteria.uniqueResult();
1068

    
1069
        return result;
1070
    }
1071

    
1072
    @Override
1073
    public List<HybridRelationship> getHybridRelationships(Set<HybridRelationshipType> types,
1074
            Integer pageSize, Integer pageNumber,
1075
            List<OrderHint> orderHints, List<String> propertyPaths) {
1076

    
1077
        Criteria criteria = getCriteria(HybridRelationship.class);
1078
        if (types != null) {
1079
            if (types.isEmpty()){
1080
                return new ArrayList<>();
1081
            }else{
1082
                criteria.add(Restrictions.in("type", types) );
1083
            }
1084
        }
1085
        addOrder(criteria,orderHints);
1086
        addPageSizeAndNumber(criteria, pageSize, pageNumber);
1087

    
1088
        @SuppressWarnings("unchecked")
1089
        List<HybridRelationship> results = criteria.list();
1090
        defaultBeanInitializer.initializeAll(results, propertyPaths);
1091

    
1092
        return results;
1093
    }
1094
}
(4-4/5)