Project

General

Profile

Download (36.4 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.HashMap;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.UUID;
17

    
18
import org.apache.log4j.Logger;
19
import org.hibernate.Criteria;
20
import org.hibernate.Query;
21
import org.hibernate.SQLQuery;
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.springframework.beans.factory.annotation.Autowired;
30
import org.springframework.beans.factory.annotation.Qualifier;
31
import org.springframework.stereotype.Repository;
32

    
33
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
34
import eu.etaxonomy.cdm.model.common.RelationshipBase;
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.SpecimenTypeDesignationStatus;
44
import eu.etaxonomy.cdm.model.name.TaxonName;
45
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
46
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
47
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
48
import eu.etaxonomy.cdm.model.view.AuditEvent;
49
import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
50
import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
51
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
52
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
53
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
54
import eu.etaxonomy.cdm.persistence.query.MatchMode;
55
import eu.etaxonomy.cdm.persistence.query.OrderHint;
56

    
57
/**
58
 * @author a.mueller
59
 *
60
 */
61
@Repository
62
@Qualifier("taxonNameDaoHibernateImpl")
63
public class TaxonNameDaoHibernateImpl extends IdentifiableDaoBase<TaxonName> implements ITaxonNameDao {
64

    
65
    private static final Logger logger = Logger.getLogger(TaxonNameDaoHibernateImpl.class);
66

    
67
    @Autowired
68
    private ITaxonDao taxonDao;
69

    
70
    @Autowired
71

    
72
    private IHomotypicalGroupDao homotypicalGroupDao;
73

    
74
    public TaxonNameDaoHibernateImpl() {
75
        super(TaxonName.class);
76
        indexedClasses = new Class[1];
77
        indexedClasses[0] = TaxonName.class;
78
    }
79

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

    
98
            if(type != null) {
99
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
100
            }
101

    
102
            return ((Long)query.getSingleResult()).intValue();
103
        }
104
    }
105

    
106
    @Override
107
    public int countNames(String queryString) {
108
        checkNotInPriorView("TaxonNameDaoHibernateImpl.countNames(String queryString)");
109
        Criteria criteria = getSession().createCriteria(TaxonName.class);
110

    
111
        if (queryString != null) {
112
            criteria.add(Restrictions.ilike("nameCache", queryString));
113
        }
114
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
115

    
116
        return ((Number)criteria.uniqueResult()).intValue();
117
    }
118

    
119
    @Override
120
    public int countNames(String queryString, MatchMode matchMode, List<Criterion> criteria) {
121

    
122
        Criteria crit = getSession().createCriteria(type);
123
        if (matchMode == MatchMode.EXACT) {
124
            crit.add(Restrictions.eq("nameCache", matchMode.queryStringFrom(queryString)));
125
        } else {
126
            crit.add(Restrictions.ilike("nameCache", matchMode.queryStringFrom(queryString)));
127
        }
128
        if(criteria != null) {
129
            for (Criterion criterion : criteria) {
130
                crit.add(criterion);
131
            }
132
        }
133

    
134
        crit.setProjection(Projections.projectionList().add(Projections.rowCount()));
135
        return ((Number)crit.uniqueResult()).intValue();
136
    }
137

    
138
    @Override
139
    public int countNames(String genusOrUninomial, String infraGenericEpithet,	String specificEpithet, String infraSpecificEpithet, Rank rank) {
140
        AuditEvent auditEvent = getAuditEventFromContext();
141
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
142
            Criteria criteria = getSession().createCriteria(TaxonName.class);
143

    
144
            /**
145
             * Given HHH-2951 - "Restrictions.eq when passed null, should create a NullRestriction"
146
             * We need to convert nulls to NullRestrictions for now
147
             */
148
            if(genusOrUninomial != null) {
149
                criteria.add(Restrictions.eq("genusOrUninomial",genusOrUninomial));
150
            } else {
151
                criteria.add(Restrictions.isNull("genusOrUninomial"));
152
            }
153

    
154
            if(infraGenericEpithet != null) {
155
                criteria.add(Restrictions.eq("infraGenericEpithet", infraGenericEpithet));
156
            } else {
157
                criteria.add(Restrictions.isNull("infraGenericEpithet"));
158
            }
159

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

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

    
172
            if(rank != null) {
173
                criteria.add(Restrictions.eq("rank", rank));
174
            }
175

    
176
            criteria.setProjection(Projections.rowCount());
177
            return ((Number)criteria.uniqueResult()).intValue();
178
        } else {
179
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonName.class,auditEvent.getRevisionNumber());
180

    
181
            if(genusOrUninomial != null) {
182
                query.add(AuditEntity.property("genusOrUninomial").eq(genusOrUninomial));
183
            } else {
184
                query.add(AuditEntity.property("genusOrUninomial").isNull());
185
            }
186

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

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

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

    
205
            if(rank != null) {
206
                query.add(AuditEntity.relatedId("rank").eq(rank.getId()));
207
            }
208

    
209
            query.addProjection(AuditEntity.id().count());
210
            return ((Long)query.getSingleResult()).intValue();
211
        }
212
    }
213

    
214
    @Override
215
    public int countNameRelationships(TaxonName name, NameRelationship.Direction direction, NameRelationshipType type) {
216

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

    
233
            if(type != null) {
234
                query.add(AuditEntity.relatedId("type").eq(type.getId()));
235
            }
236

    
237
            return ((Long)query.getSingleResult()).intValue();
238
        }
239
    }
240

    
241

    
242
    @Override
243
    public int countTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status) {
244
        checkNotInPriorView("countTypeDesignations(TaxonName name, SpecimenTypeDesignationStatus status)");
245
        Query query = null;
246
        if(status == null) {
247
            query = getSession().createQuery("select count(designation) from TypeDesignationBase designation join designation.typifiedNames name where name = :name");
248
        } else {
249
            query = getSession().createQuery("select count(designation) from TypeDesignationBase designation join designation.typifiedNames name where name = :name and designation.typeStatus = :status");
250
            query.setParameter("status", status);
251
        }
252
        query.setParameter("name",name);
253
        return ((Long)query.uniqueResult()).intValue();
254
    }
255

    
256
    @Override
257
    public List<HybridRelationship> getHybridNames(INonViralName name, HybridRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
258
        AuditEvent auditEvent = getAuditEventFromContext();
259
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
260
            Criteria criteria = getSession().createCriteria(HybridRelationship.class);
261
            criteria.add(Restrictions.eq("relatedFrom", name));
262
            if(type != null) {
263
                criteria.add(Restrictions.eq("type", type));
264
            }
265

    
266
            if(pageSize != null) {
267
                criteria.setMaxResults(pageSize);
268
                if(pageNumber != null) {
269
                    criteria.setFirstResult(pageNumber * pageSize);
270
                } else {
271
                    criteria.setFirstResult(0);
272
                }
273
            }
274

    
275
            addOrder(criteria, orderHints);
276

    
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
            List<HybridRelationship> results =  query.getResultList();
298
            defaultBeanInitializer.initializeAll(results, propertyPaths);
299
            return results;
300
        }
301
    }
302

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

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

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

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

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

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

    
348
            List<NameRelationship> results = query.getResultList();
349
            defaultBeanInitializer.initializeAll(results, propertyPaths);
350
            return results;
351
        }
352
    }
353

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

    
359
    @Override
360
    public <T extends TypeDesignationBase> List<T> getTypeDesignations(TaxonName name,
361
                Class<T> type,
362
                TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber,
363
                List<String> propertyPaths){
364
        checkNotInPriorView("getTypeDesignations(TaxonName name,TypeDesignationStatusBase status, Integer pageSize, Integer pageNumber,	List<String> propertyPaths)");
365
        Query query = null;
366
        String queryString = "select designation from TypeDesignationBase designation join designation.typifiedNames name where name = :name";
367

    
368
        if(status != null) {
369
            queryString +=  " and designation.typeStatus = :status";
370
        }
371
        if(type != null){
372
            queryString +=  " and designation.class = :type";
373
        }
374

    
375
        query = getSession().createQuery(queryString);
376

    
377
        if(status != null) {
378
            query.setParameter("status", status);
379
        }
380
        if(type != null){
381
            query.setParameter("type", type.getSimpleName());
382
        }
383

    
384
        query.setParameter("name",name);
385

    
386
        if(pageSize != null) {
387
            query.setMaxResults(pageSize);
388
            if(pageNumber != null) {
389
                query.setFirstResult(pageNumber * pageSize);
390
            } else {
391
                query.setFirstResult(0);
392
            }
393
        }
394
        return defaultBeanInitializer.initializeAll((List<T>)query.list(), propertyPaths);
395
    }
396

    
397

    
398
    public List<TaxonName> searchNames(String queryString, MatchMode matchMode, Integer pageSize, Integer pageNumber) {
399
        checkNotInPriorView("TaxonNameDaoHibernateImpl.searchNames(String queryString, Integer pageSize, Integer pageNumber)");
400
        Criteria criteria = getSession().createCriteria(TaxonName.class);
401

    
402
        if (queryString != null) {
403
            criteria.add(Restrictions.ilike("nameCache", queryString));
404
        }
405
        if(pageSize != null) {
406
            criteria.setMaxResults(pageSize);
407
            if(pageNumber != null) {
408
                criteria.setFirstResult(pageNumber * pageSize);
409
            } else {
410
                criteria.setFirstResult(0);
411
            }
412
        }
413
        List<TaxonName> results = criteria.list();
414
        return results;
415
    }
416

    
417

    
418
    @Override
419
    public List<TaxonName> searchNames(String queryString, Integer pageSize, Integer pageNumber) {
420
        return searchNames(queryString, MatchMode.BEGINNING, pageSize, pageNumber);
421
    }
422

    
423

    
424
    @Override
425
    public List<TaxonName> searchNames(String genusOrUninomial,String infraGenericEpithet, String specificEpithet,	String infraSpecificEpithet, Rank rank, Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,
426
            List<String> propertyPaths) {
427
        AuditEvent auditEvent = getAuditEventFromContext();
428
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
429
            Criteria criteria = getSession().createCriteria(TaxonName.class);
430

    
431
            /**
432
             * Given HHH-2951 - "Restrictions.eq when passed null, should create a NullRestriction"
433
             * We need to convert nulls to NullRestrictions for now
434
             */
435
            if(genusOrUninomial != null) {
436
                criteria.add(Restrictions.eq("genusOrUninomial",genusOrUninomial));
437
            } else {
438
                criteria.add(Restrictions.isNull("genusOrUninomial"));
439
            }
440

    
441
            if(infraGenericEpithet != null) {
442
                criteria.add(Restrictions.eq("infraGenericEpithet", infraGenericEpithet));
443
            } else {
444
                criteria.add(Restrictions.isNull("infraGenericEpithet"));
445
            }
446

    
447
            if(specificEpithet != null) {
448
                criteria.add(Restrictions.eq("specificEpithet", specificEpithet));
449
            } else {
450
                criteria.add(Restrictions.isNull("specificEpithet"));
451
            }
452

    
453
            if(infraSpecificEpithet != null) {
454
                criteria.add(Restrictions.eq("infraSpecificEpithet",infraSpecificEpithet));
455
            } else {
456
                criteria.add(Restrictions.isNull("infraSpecificEpithet"));
457
            }
458

    
459
            if(rank != null) {
460
                criteria.add(Restrictions.eq("rank", rank));
461
            }
462

    
463
            if(pageSize != null) {
464
                criteria.setMaxResults(pageSize);
465
                if(pageNumber != null) {
466
                    criteria.setFirstResult(pageNumber * pageSize);
467
                } else {
468
                    criteria.setFirstResult(0);
469
                }
470
            }
471

    
472
            addOrder(criteria, orderHints);
473

    
474
            List<TaxonName> results = criteria.list();
475
            defaultBeanInitializer.initializeAll(results, propertyPaths);
476
            return results;
477
        } else {
478
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonName.class,auditEvent.getRevisionNumber());
479

    
480
            if(genusOrUninomial != null) {
481
                query.add(AuditEntity.property("genusOrUninomial").eq(genusOrUninomial));
482
            } else {
483
                query.add(AuditEntity.property("genusOrUninomial").isNull());
484
            }
485

    
486
            if(infraGenericEpithet != null) {
487
                query.add(AuditEntity.property("infraGenericEpithet").eq(infraGenericEpithet));
488
            } else {
489
                query.add(AuditEntity.property("infraGenericEpithet").isNull());
490
            }
491

    
492
            if(specificEpithet != null) {
493
                query.add(AuditEntity.property("specificEpithet").eq(specificEpithet));
494
            } else {
495
                query.add(AuditEntity.property("specificEpithet").isNull());
496
            }
497

    
498
            if(infraSpecificEpithet != null) {
499
                query.add(AuditEntity.property("infraSpecificEpithet").eq(infraSpecificEpithet));
500
            } else {
501
                query.add(AuditEntity.property("infraSpecificEpithet").isNull());
502
            }
503

    
504
            if(rank != null) {
505
                query.add(AuditEntity.relatedId("rank").eq(rank.getId()));
506
            }
507

    
508
            if(pageSize != null) {
509
                query.setMaxResults(pageSize);
510
                if(pageNumber != null) {
511
                    query.setFirstResult(pageNumber * pageSize);
512
                } else {
513
                    query.setFirstResult(0);
514
                }
515
            }
516

    
517
            List<TaxonName> results = query.getResultList();
518
            defaultBeanInitializer.initializeAll(results, propertyPaths);
519
            return results;
520
        }
521
    }
522

    
523
    @Override
524
    public List<? extends TaxonName> findByName(boolean doIncludeAuthors,
525
            String queryString, MatchMode matchmode, Integer pageSize,
526
            Integer pageNumber, List<Criterion> criteria, List<String> propertyPaths) {
527

    
528
        Criteria crit = getSession().createCriteria(type);
529
        Criterion nameCacheLike;
530
        if (matchmode == MatchMode.EXACT) {
531
            nameCacheLike = Restrictions.eq("nameCache", matchmode.queryStringFrom(queryString));
532
        } else {
533
            nameCacheLike = Restrictions.ilike("nameCache", matchmode.queryStringFrom(queryString));
534
        }
535
        Criterion notNull = Restrictions.isNotNull("nameCache");
536
        LogicalExpression nameCacheExpression = Restrictions.and(notNull, nameCacheLike);
537

    
538
        Criterion titleCacheLike;
539
        if (matchmode == MatchMode.EXACT) {
540
            titleCacheLike = Restrictions.eq("titleCache", matchmode.queryStringFrom(queryString));
541
        } else {
542
            titleCacheLike =Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString));
543
        }
544
        Criterion isNull = Restrictions.isNull("nameCache");
545
        LogicalExpression titleCacheExpression = Restrictions.and(isNull, titleCacheLike);
546

    
547
        LogicalExpression orExpression = Restrictions.or(titleCacheExpression, nameCacheExpression);
548

    
549
        Criterion finalCriterion = doIncludeAuthors ? titleCacheLike : orExpression;
550

    
551
        crit.add(finalCriterion);
552
        if(criteria != null){
553
            for (Criterion criterion : criteria) {
554
                crit.add(criterion);
555
            }
556
        }
557
        crit.addOrder(Order.asc("nameCache"));
558

    
559
        if(pageSize != null) {
560
            crit.setMaxResults(pageSize);
561
            if(pageNumber != null) {
562
                crit.setFirstResult(pageNumber * pageSize);
563
            }
564
        }
565

    
566
        @SuppressWarnings("unchecked")
567
        List<? extends TaxonName> results = crit.list();
568
        defaultBeanInitializer.initializeAll(results, propertyPaths);
569

    
570
        return results;
571
    }
572

    
573
    @Override
574
    public List<? extends TaxonName> findByTitle(String queryString,
575
            MatchMode matchmode, Integer pageSize, Integer pageNumber, List<Criterion> criteria, List<String> propertyPaths) {
576

    
577
        Criteria crit = getSession().createCriteria(type);
578
        if (matchmode == MatchMode.EXACT) {
579
            crit.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(queryString)));
580
        } else {
581
            crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
582
        }
583
        if(criteria != null){
584
            for (Criterion criterion : criteria) {
585
                crit.add(criterion);
586
            }
587
        }
588
        crit.addOrder(Order.asc("titleCache"));
589

    
590
        if(pageSize != null) {
591
            crit.setMaxResults(pageSize);
592
            if(pageNumber != null) {
593
                crit.setFirstResult(pageNumber * pageSize);
594
            }
595
        }
596

    
597
        List<? extends TaxonName> results = crit.list();
598
        defaultBeanInitializer.initializeAll(results, propertyPaths);
599

    
600
        return results;
601
    }
602

    
603

    
604
    @Override
605
    public TaxonName findByUuid(UUID uuid, List<Criterion> criteria, List<String> propertyPaths) {
606

    
607
        Criteria crit = getSession().createCriteria(type);
608

    
609
        if (uuid != null) {
610
            crit.add(Restrictions.eq("uuid", uuid));
611
        } else {
612
            logger.warn("UUID is NULL");
613
            return null;
614
        }
615
        if(criteria != null){
616
            for (Criterion criterion : criteria) {
617
                crit.add(criterion);
618
            }
619
        }
620
        crit.addOrder(Order.asc("uuid"));
621

    
622
        List<? extends TaxonName> results = crit.list();
623
        if (results.size() == 1) {
624
            defaultBeanInitializer.initializeAll(results, propertyPaths);
625
            TaxonName taxonName = results.iterator().next();
626
            return taxonName;
627
        } else if (results.size() > 1) {
628
            logger.error("Multiple results for UUID: " + uuid);
629
        } else if (results.size() == 0) {
630
            logger.info("No results for UUID: " + uuid);
631
        }
632

    
633
        return null;
634
    }
635

    
636
    @Override
637
    public List<RelationshipBase> getAllRelationships(Integer limit, Integer start) {
638
        AuditEvent auditEvent = getAuditEventFromContext();
639
        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
640
            // for some reason the HQL .class discriminator didn't work here so I created this preliminary
641
            // implementation for now. Should be cleaned in future.
642

    
643
            List<RelationshipBase> result = new ArrayList<RelationshipBase>();
644

    
645
            int nameRelSize = countAllRelationships(NameRelationship.class);
646
            if (nameRelSize > start){
647

    
648
                String hql = " FROM %s as rb ORDER BY rb.id ";
649
                hql = String.format(hql, NameRelationship.class.getSimpleName());
650
                Query query = getSession().createQuery(hql);
651
                query.setFirstResult(start);
652
                if (limit != null){
653
                    query.setMaxResults(limit);
654
                }
655
                result = query.list();
656
            }
657
            limit = limit - result.size();
658
            if (limit > 0){
659
                String hql = " FROM HybridRelationship as rb ORDER BY rb.id ";
660
                hql = String.format(hql, HybridRelationship.class.getSimpleName());
661
                Query query = getSession().createQuery(hql);
662
                start = (nameRelSize > start) ? 0 : (start - nameRelSize);
663
                query.setFirstResult(start);
664
                if (limit != null){
665
                    query.setMaxResults(limit);
666
                }
667
                result.addAll( query.list());
668
            }
669
            return result;
670
        } else {
671
            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(RelationshipBase.class,auditEvent.getRevisionNumber());
672
            return query.getResultList();
673
        }
674
    }
675

    
676

    
677
    /**
678
     * TODO not yet in interface
679
     * @param clazz
680
     * @return
681
     */
682
    public int countAllRelationships(Class<? extends RelationshipBase> clazz) {
683
        if (clazz != null && ! NameRelationship.class.isAssignableFrom(clazz) && ! HybridRelationship.class.isAssignableFrom(clazz) ){
684
            throw new RuntimeException("Class must be assignable by a taxon or snonym relation");
685
        }
686
        int size = 0;
687

    
688
        if (clazz == null || NameRelationship.class.isAssignableFrom(clazz)){
689
            String hql = " SELECT count(rel) FROM NameRelationship rel";
690
            size += (Long)getSession().createQuery(hql).list().get(0);
691
        }
692
        if (clazz == null || HybridRelationship.class.isAssignableFrom(clazz)){
693
            String hql = " SELECT count(rel) FROM HybridRelationship rel";
694
            size += (Long)getSession().createQuery(hql).list().get(0);
695
        }
696
        return size;
697
    }
698

    
699

    
700
    @Override
701
    public Integer countByName(String queryString, MatchMode matchmode, List<Criterion> criteria) {
702
        //TODO improve performance
703
        boolean includeAuthors = false;
704
        List<? extends TaxonName> results = findByName(
705
                includeAuthors,queryString, matchmode, null, null, criteria, null);
706
        return results.size();
707

    
708
    }
709

    
710
    @Override
711
    public List<UuidAndTitleCache> getUuidAndTitleCacheOfNames(Integer limit, String pattern) {
712
        String queryString = "SELECT uuid, id, fullTitleCache FROM TaxonName LIMIT " + limit;
713

    
714
        @SuppressWarnings("unchecked")
715
        List<Object[]> result = getSession().createSQLQuery(queryString).list();
716

    
717
        if(result.size() == 0){
718
            return null;
719
        }else{
720
            List<UuidAndTitleCache> list = new ArrayList<UuidAndTitleCache>(result.size());
721

    
722
            for (Object object : result){
723

    
724
                Object[] objectArray = (Object[]) object;
725

    
726
                UUID uuid = UUID.fromString((String) objectArray[0]);
727
                Integer id = (Integer) objectArray[1];
728
                String titleCache = (String) objectArray[2];
729

    
730
                list.add(new UuidAndTitleCache(type, uuid, id, titleCache));
731
            }
732

    
733
            return list;
734
        }
735
    }
736

    
737
    @Override
738
    public long countByName(Class<? extends TaxonName> clazz,String queryString, MatchMode matchmode, List<Criterion> criteria) {
739
        return super.countByParam(clazz, "nameCache", queryString, matchmode, criteria);
740
    }
741

    
742
    @Override
743
    public List<TaxonName> findByName(Class<? extends TaxonName> clazz,	String queryString, MatchMode matchmode, List<Criterion> criteria,Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,	List<String> propertyPaths) {
744
        return super.findByParam(clazz, "nameCache", queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
745
    }
746

    
747
    @Override
748
    public UUID delete (TaxonName persistentObject){
749
        Set<TaxonBase> taxonBases = persistentObject.getTaxonBases();
750

    
751
        if (persistentObject == null){
752
            logger.warn(type.getName() + " was 'null'");
753
            return null;
754
        }
755
        getSession().saveOrUpdate(persistentObject);
756
        UUID persUuid = persistentObject.getUuid();
757
       // persistentObject = this.load(persUuid);
758
        UUID homotypicalGroupUUID = persistentObject.getHomotypicalGroup().getUuid();
759

    
760

    
761
        for (TaxonBase taxonBase: taxonBases){
762
            taxonDao.delete(taxonBase);
763
        }
764
        HomotypicalGroup homotypicalGroup = homotypicalGroupDao.load(homotypicalGroupUUID);
765
        homotypicalGroup = HibernateProxyHelper.deproxy(homotypicalGroup, HomotypicalGroup.class);
766

    
767
        if (homotypicalGroup != null){
768
            if (homotypicalGroup.getTypifiedNames().contains(persistentObject)){
769
                homotypicalGroup.getTypifiedNames().remove(persistentObject);
770
                homotypicalGroupDao.saveOrUpdate(homotypicalGroup);
771
            }
772

    
773
        }
774

    
775
        getSession().delete(persistentObject);
776
        if (homotypicalGroup.getTypifiedNames().isEmpty()){
777
            homotypicalGroupDao.delete(homotypicalGroup);
778
        }
779
        return persistentObject.getUuid();
780
    }
781

    
782

    
783
    @Override
784
    public IZoologicalName findZoologicalNameByUUID(UUID uuid){
785
        Criteria criteria = getSession().createCriteria(type);
786
        if (uuid != null) {
787
            criteria.add(Restrictions.eq("uuid", uuid));
788
        } else {
789
            logger.warn("UUID is NULL");
790
            return null;
791
        }
792

    
793
        @SuppressWarnings("unchecked")
794
        List<? extends TaxonName> results = criteria.list();
795
        if (results.size() == 1) {
796
            defaultBeanInitializer.initializeAll(results, null);
797
            TaxonName taxonName = results.iterator().next();
798
            if (taxonName.isZoological()) {
799
                IZoologicalName zoologicalName = taxonName;
800
                return zoologicalName;
801
            } else {
802
                logger.warn("This UUID (" + uuid + ") does not belong to a ZoologicalName. It belongs to: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
803
            }
804
        } else if (results.size() > 1) {
805
            logger.error("Multiple results for UUID: " + uuid);
806
        } else if (results.size() == 0) {
807
            logger.info("No results for UUID: " + uuid);
808
        }
809
        return null;
810
    }
811

    
812
    @Override
813
    public List<HashMap<String,String>> getNameRecords(){
814
    	String sql= "SELECT"
815
    			+ "  (SELECT famName.namecache FROM TaxonNode famNode"
816
    			+ "  LEFT OUTER JOIN TaxonBase famTax ON famNode.taxon_id = famTax.id"
817
    			+ " LEFT OUTER JOIN TaxonName famName ON famTax.name_id = famName.id"
818
    			+ " WHERE famName.rank_id = 795 AND famNode.treeIndex = SUBSTRING(tn.treeIndex, 1, length(famNode.treeIndex))"
819
    			+ "	) as famName, "
820
    			+ " (SELECT famName.namecache FROM TaxonNode famNode "
821
    			+ " LEFT OUTER JOIN TaxonBase famTax ON famNode.taxon_id = famTax.id "
822
    			+ " LEFT OUTER JOIN TaxonName famName ON famTax.name_id = famName.id "
823
    			+ " WHERE famName.rank_id = 795 AND famNode.treeIndex = SUBSTRING(tnAcc.treeIndex, 1, length(famNode.treeIndex))"
824
    			+ "	) as accFamName,tb.DTYPE, tb.id as TaxonID ,tb.titleCache taxonTitle,  tnb.rank_id as RankID, tnb.id as NameID,"
825
    			+ " tnb.namecache as name, tnb.titleCache as nameAuthor, tnb.fullTitleCache nameAndNomRef,"
826
    			+ "	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,"
827
    			+ "	nameType.namecache nameType, nameType.titleCache nameTypeAuthor, nameType.fullTitleCache nameTypeFullTitle, nameTypeRef.titleCache nameTypeRef, inRef.seriespart as inRefSeries, inRef.datepublished_start inRefPublishedStart, inRef.datepublished_end inRefPublishedEnd, inRef.volume as inRefVolume"
828
    			+ " FROM TaxonBase tb"
829
    			+ " LEFT OUTER JOIN TaxonName tnb ON tb.name_id = tnb.id"
830
    			+ "	LEFT OUTER JOIN Reference r ON tnb.nomenclaturalreference_id = r.id"
831
    			+ "	LEFT OUTER JOIN TaxonNode tn ON tn.taxon_id = tb.id"
832
    			+ "	LEFT OUTER JOIN TaxonName_TypeDesignationBase typeMN ON typeMN.TaxonName_id = tnb.id"
833
    			+ " LEFT OUTER JOIN TypeDesignationBase tdb ON tdb.id = typeMN.typedesignations_id"
834
    			+ "	LEFT OUTER JOIN TaxonName nameType ON tdb.typename_id = nameType.id"
835
    			+ "	LEFT OUTER JOIN Reference nameTypeRef ON nameType.nomenclaturalreference_id = nameTypeRef.id"
836
    			+ "		LEFT OUTER JOIN Reference inRef ON inRef.id = r.inreference_id"
837
    			+ "	LEFT OUTER JOIN TaxonBase accT ON accT.id = tb.acceptedTaxon_id"
838
    			+ "		LEFT OUTER JOIN TaxonNode tnAcc ON tnAcc.taxon_id = accT.id"
839
    			+ "	ORDER BY DTYPE, famName, accFamName,  tnb.rank_id ,tb.titleCache";
840

    
841

    
842
    	SQLQuery query = getSession().createSQLQuery(sql);
843
    	List result = query.list();
844
    	 //Delimiter used in CSV file
845

    
846

    
847
		List<HashMap<String,String>> nameRecords = new ArrayList();
848
		HashMap<String,String> nameRecord = new HashMap<String,String>();
849
		for(Object object : result)
850
         {
851
			Object[] row = (Object[])object;
852
			nameRecord = new HashMap<String,String>();
853
			nameRecord.put("famName",(String)row[0]);
854
			nameRecord.put("accFamName",(String)row[1]);
855

    
856
			nameRecord.put("DTYPE",(String)row[2]);
857
			nameRecord.put("TaxonID",String.valueOf(row[3]));
858
			nameRecord.put("taxonTitle",(String)row[4]);
859
            nameRecord.put("RankID",String.valueOf(row[5]));
860
            nameRecord.put("NameID",String.valueOf(row[6]));
861
            nameRecord.put("name",(String)row[7]);
862
            nameRecord.put("nameAuthor",(String)row[8]);
863
            nameRecord.put("nameAndNomRef",(String)row[9]);
864
            nameRecord.put("nomRef",(String)row[10]);
865
            nameRecord.put("nomRefAbbrevTitle",(String)row[11]);
866
            nameRecord.put("nomRefTitle",(String)row[12]);
867
            nameRecord.put("nomRefPublishedStart",(String)row[13]);
868
            nameRecord.put("nomRefPublishedEnd",(String)row[14]);
869
            nameRecord.put("nomRefPages",(String)row[15]);
870
            nameRecord.put("inRefAbbrevTitle",(String)row[16]);
871
            nameRecord.put("detail",(String)row[17]);
872
            nameRecord.put("nameType",(String)row[18]);
873
            nameRecord.put("nameTypeAuthor",(String)row[19]);
874
            nameRecord.put("nameTypeFullTitle",(String)row[20]);
875
            nameRecord.put("nameTypeRef",(String)row[21]);
876
            nameRecord.put("inRefSeries",(String)row[22]);
877
            nameRecord.put("inRefPublishedStart",(String)row[23]);
878
            nameRecord.put("inRefPublishedEnd",(String)row[24]);
879
            nameRecord.put("inRefVolume",(String)row[25]);
880
            nameRecords.add(nameRecord);
881
	   }
882

    
883
		return nameRecords;
884
    }
885

    
886

    
887

    
888

    
889
}
(4-4/5)