Project

General

Profile

Download (48.9 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.common;
11

    
12
import java.lang.reflect.Field;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.EnumSet;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import org.apache.log4j.Logger;
25
import org.hibernate.Criteria;
26
import org.hibernate.FlushMode;
27
import org.hibernate.HibernateException;
28
import org.hibernate.LockOptions;
29
import org.hibernate.NonUniqueObjectException;
30
import org.hibernate.Query;
31
import org.hibernate.Session;
32
import org.hibernate.criterion.Criterion;
33
import org.hibernate.criterion.DetachedCriteria;
34
import org.hibernate.criterion.Disjunction;
35
import org.hibernate.criterion.Example;
36
import org.hibernate.criterion.Example.PropertySelector;
37
import org.hibernate.criterion.LogicalExpression;
38
import org.hibernate.criterion.Order;
39
import org.hibernate.criterion.ProjectionList;
40
import org.hibernate.criterion.Projections;
41
import org.hibernate.criterion.Restrictions;
42
import org.hibernate.criterion.Subqueries;
43
import org.hibernate.envers.AuditReader;
44
import org.hibernate.envers.AuditReaderFactory;
45
import org.hibernate.envers.query.AuditQuery;
46
import org.hibernate.metadata.ClassMetadata;
47
import org.hibernate.sql.JoinType;
48
import org.hibernate.type.Type;
49
import org.joda.time.DateTime;
50
import org.springframework.beans.factory.annotation.Autowired;
51
import org.springframework.dao.DataAccessException;
52
import org.springframework.dao.InvalidDataAccessApiUsageException;
53
import org.springframework.security.core.Authentication;
54
import org.springframework.security.core.context.SecurityContextHolder;
55
import org.springframework.stereotype.Repository;
56
import org.springframework.util.ReflectionUtils;
57

    
58
import eu.etaxonomy.cdm.model.common.CdmBase;
59
import eu.etaxonomy.cdm.model.common.IPublishable;
60
import eu.etaxonomy.cdm.model.common.VersionableEntity;
61
import eu.etaxonomy.cdm.model.permission.User;
62
import eu.etaxonomy.cdm.model.view.AuditEvent;
63
import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
64
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
65
import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;
66
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
67
import eu.etaxonomy.cdm.persistence.dto.MergeResult;
68
import eu.etaxonomy.cdm.persistence.hibernate.PostMergeEntityListener;
69
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadata;
70
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadataFactory;
71
import eu.etaxonomy.cdm.persistence.query.Grouping;
72
import eu.etaxonomy.cdm.persistence.query.MatchMode;
73
import eu.etaxonomy.cdm.persistence.query.OrderHint;
74

    
75
/**
76
 * @author a.mueller FIXME CdmEntityDaoBase is abstract, can it be annotated
77
 *         with @Repository?
78
 */
79
@Repository
80
public abstract class CdmEntityDaoBase<T extends CdmBase>
81
        extends DaoBase
82
        implements ICdmEntityDao<T> {
83

    
84
    private static final Logger logger = Logger.getLogger(CdmEntityDaoBase.class);
85

    
86
    protected int flushAfterNo = 1000; // large numbers may cause
87
                                       // synchronisation errors when commiting
88
                                       // the session !!
89

    
90
    protected Class<T> type;
91

    
92
    @Autowired
93
    // @Qualifier("defaultBeanInitializer")
94
    protected IBeanInitializer defaultBeanInitializer;
95

    
96
    public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer) {
97
        this.defaultBeanInitializer = defaultBeanInitializer;
98
    }
99

    
100
    @Autowired
101
    private ReferringObjectMetadataFactory referringObjectMetadataFactory;
102

    
103
    protected static final EnumSet<Operator> LEFTOUTER_OPS = EnumSet.of(Operator.AND_NOT, Operator.OR, Operator.OR_NOT);
104

    
105
    public CdmEntityDaoBase(Class<T> type) {
106
        this.type = type;
107
        assert type != null;
108
        logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");
109
    }
110

    
111
    @Override
112
    public void lock(T t, LockOptions lockOptions) {
113
        getSession().buildLockRequest(lockOptions).lock(t);
114
    }
115

    
116
    @Override
117
    public void refresh(T t, LockOptions lockOptions, List<String> propertyPaths) {
118
        getSession().refresh(t, lockOptions);
119
        defaultBeanInitializer.initialize(t, propertyPaths);
120
    }
121

    
122
    // TODO this method should be moved to a concrete class (not typed)
123
    public UUID saveCdmObj(CdmBase cdmObj) throws DataAccessException {
124
        getSession().saveOrUpdate(cdmObj);
125
        return cdmObj.getUuid();
126
    }
127

    
128
    // TODO: Replace saveCdmObj() by saveCdmObject_
129
    private UUID saveCdmObject_(T cdmObj) {
130
        getSession().saveOrUpdate(cdmObj);
131
        return cdmObj.getUuid();
132
    }
133

    
134
    // TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of
135
    // ServiceBase.saveCdmObjectAll()?
136
    // TODO: why does this use saveCdmObject_ which actually savesOrUpdateds
137
    // data ?
138
    @Override
139
    public Map<UUID, T> saveAll(Collection<T> cdmObjCollection) {
140
        int types = cdmObjCollection.getClass().getTypeParameters().length;
141
        if (types > 0) {
142
            if (logger.isDebugEnabled()) {
143
                logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);
144
            }
145
        }
146

    
147
        Map<UUID, T> resultMap = new HashMap<>();
148
        Iterator<T> iterator = cdmObjCollection.iterator();
149
        int i = 0;
150
        while (iterator.hasNext()) {
151
            if (((i % 2000) == 0) && (i > 0)) {
152
                logger.debug("Saved " + i + " objects");
153
            }
154
            T cdmObj = iterator.next();
155
            UUID uuid = saveCdmObject_(cdmObj);
156
            if (logger.isDebugEnabled()) {
157
                logger.debug("Save cdmObj: " + (cdmObj == null ? null : cdmObj.toString()));
158
            }
159
            resultMap.put(uuid, cdmObj);
160
            i++;
161
            if ((i % flushAfterNo) == 0) {
162
                try {
163
                    if (logger.isDebugEnabled()) {
164
                        logger.debug("flush");
165
                    }
166
                    flush();
167
                } catch (Exception e) {
168
                    logger.error("An exception occurred when trying to flush data");
169
                    e.printStackTrace();
170
                    throw new RuntimeException(e);
171
                }
172
            }
173
        }
174

    
175
        if (logger.isInfoEnabled()) {
176
            logger.info("Saved " + i + " objects");
177
        }
178
        return resultMap;
179
    }
180

    
181
    private UUID saveOrUpdateCdmObject(T cdmObj) {
182
        getSession().saveOrUpdate(cdmObj);
183
        return cdmObj.getUuid();
184
    }
185

    
186
    @Override
187
    public Map<UUID, T> saveOrUpdateAll(Collection<T> cdmObjCollection) {
188
        int types = cdmObjCollection.getClass().getTypeParameters().length;
189
        if (types > 0) {
190
            if (logger.isDebugEnabled()) {
191
                logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);
192
            }
193
        }
194

    
195
        Map<UUID, T> resultMap = new HashMap<>();
196
        Iterator<T> iterator = cdmObjCollection.iterator();
197
        int i = 0;
198
        while (iterator.hasNext()) {
199
            if (((i % 2000) == 0) && (i > 0)) {
200
                logger.debug("Saved " + i + " objects");
201
            }
202
            T cdmObj = iterator.next();
203
            UUID uuid = saveOrUpdateCdmObject(cdmObj);
204
            if (logger.isDebugEnabled()) {
205
                logger.debug("Save cdmObj: " + (cdmObj == null ? null : cdmObj.toString()));
206
            }
207
            resultMap.put(uuid, cdmObj);
208
            i++;
209
            if ((i % flushAfterNo) == 0) {
210
                try {
211
                    if (logger.isDebugEnabled()) {
212
                        logger.debug("flush");
213
                    }
214
                    flush();
215
                } catch (Exception e) {
216
                    logger.error("An exception occurred when trying to flush data");
217
                    e.printStackTrace();
218
                    throw new RuntimeException(e);
219
                }
220
            }
221
        }
222

    
223
        if (logger.isInfoEnabled()) {
224
            logger.info("Saved " + i + " objects");
225
        }
226
        return resultMap;
227
    }
228

    
229
    @Override
230
    public T replace(T x, T y) {
231
        if (x.equals(y)) {
232
            return y;
233
        }
234

    
235
        Class<?> commonClass = x.getClass();
236
        if (y != null) {
237
            while (!commonClass.isAssignableFrom(y.getClass())) {
238
                if (commonClass.equals(type)) {
239
                    throw new RuntimeException();
240
                }
241
                commonClass = commonClass.getSuperclass();
242
            }
243
        }
244

    
245
        getSession().merge(x);
246

    
247
        Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());
248

    
249
        for (ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {
250

    
251
            List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x, getSession());
252

    
253
            for (CdmBase referringObject : referringObjects) {
254
                try {
255
                    referringObjectMetadata.replace(referringObject, x, y);
256
                    getSession().update(referringObject);
257

    
258
                } catch (IllegalArgumentException e) {
259
                    throw new RuntimeException(e.getMessage(), e);
260
                } catch (IllegalAccessException e) {
261
                    throw new RuntimeException(e.getMessage(), e);
262
                }
263
            }
264
        }
265
        return y;
266
    }
267

    
268
    @Override
269
    public Session getSession() throws DataAccessException {
270
        return super.getSession();
271
    }
272

    
273
    @Override
274
    public void clear() throws DataAccessException {
275
        Session session = getSession();
276
        session.clear();
277
        if (logger.isDebugEnabled()) {
278
            logger.debug("dao clear end");
279
        }
280
    }
281

    
282
    @Override
283
    public MergeResult<T> merge(T transientObject, boolean returnTransientEntity) throws DataAccessException {
284
        Session session = getSession();
285
        PostMergeEntityListener.addSession(session);
286
        MergeResult<T> result = null;
287
        try {
288
            @SuppressWarnings("unchecked")
289
            T persistentObject = (T) session.merge(transientObject);
290
            if (logger.isDebugEnabled()) {
291
                logger.debug("dao merge end");
292
            }
293

    
294
            if (returnTransientEntity) {
295
                if (transientObject != null && persistentObject != null) {
296
                    transientObject.setId(persistentObject.getId());
297
                }
298
                result = new MergeResult(transientObject, PostMergeEntityListener.getNewEntities(session));
299
            } else {
300
                result = new MergeResult(persistentObject, null);
301
            }
302
            return result;
303
        } finally {
304
            PostMergeEntityListener.removeSession(session);
305
        }
306
    }
307

    
308
    @Override
309
    public T merge(T transientObject) throws DataAccessException {
310
        Session session = getSession();
311
        @SuppressWarnings("unchecked")
312
        T persistentObject = (T) session.merge(transientObject);
313
        if (logger.isDebugEnabled()) {
314
            logger.debug("dao merge end");
315
        }
316
        return persistentObject;
317
    }
318

    
319
    @Override
320
    public UUID saveOrUpdate(T transientObject) throws DataAccessException {
321
        if (transientObject == null) {
322
            logger.warn("Object to save should not be null. NOP");
323
            return null;
324
        }
325
        try {
326
            if (logger.isDebugEnabled()) {
327
                logger.debug("dao saveOrUpdate start...");
328
            }
329
            if (logger.isDebugEnabled()) {
330
                logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:"
331
                        + transientObject.getId() + ", UUID: " + transientObject.getUuid());
332
            }
333
            Session session = getSession();
334
            if (transientObject.getId() != 0 && VersionableEntity.class.isAssignableFrom(transientObject.getClass())) {
335
                VersionableEntity versionableEntity = (VersionableEntity) transientObject;
336
                versionableEntity.setUpdated(new DateTime());
337
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
338
                if (authentication != null && authentication.getPrincipal() != null
339
                        && authentication.getPrincipal() instanceof User) {
340
                    User user = (User) authentication.getPrincipal();
341
                    versionableEntity.setUpdatedBy(user);
342
                }
343
            }
344
            session.saveOrUpdate(transientObject);
345
            if (logger.isDebugEnabled()) {
346
                logger.debug("dao saveOrUpdate end");
347
            }
348
            return transientObject.getUuid();
349
        } catch (NonUniqueObjectException e) {
350
            logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj). ID=" + e.getIdentifier() + ". Class="
351
                    + e.getEntityName());
352
            logger.error(e.getMessage());
353

    
354
            e.printStackTrace();
355
            throw e;
356
        } catch (HibernateException e) {
357

    
358
            e.printStackTrace();
359
            throw e;
360
        }
361
    }
362

    
363
    @Override
364
    public <S extends T> S save(S newInstance) throws DataAccessException {
365
        if (newInstance == null) {
366
            logger.warn("Object to save should not be null. NOP");
367
            return null;
368
        }
369
        getSession().save(newInstance);
370
        return newInstance;
371
    }
372

    
373
    @Override
374
    public UUID update(T transientObject) throws DataAccessException {
375
        if (transientObject == null) {
376
            logger.warn("Object to update should not be null. NOP");
377
            return null;
378
        }
379
        getSession().update(transientObject);
380
        return transientObject.getUuid();
381
    }
382

    
383
    @Override
384
    public UUID refresh(T persistentObject) throws DataAccessException {
385
        getSession().refresh(persistentObject);
386
        return persistentObject.getUuid();
387
    }
388

    
389
    @Override
390
    public UUID delete(T persistentObject) throws DataAccessException {
391
        if (persistentObject == null) {
392
            logger.warn(type.getName() + " was 'null'");
393
            return null;
394
        }
395

    
396
        // Merge the object in if it is detached
397
        //
398
        // I think this is preferable to catching lazy initialization errors
399
        // as that solution only swallows and hides the exception, but doesn't
400
        // actually solve it.
401
        persistentObject = (T) getSession().merge(persistentObject);
402
        getSession().delete(persistentObject);
403
        return persistentObject.getUuid();
404
    }
405

    
406
    @Override
407
    public T findById(int id) throws DataAccessException {
408
        return getSession().get(type, id);
409
    }
410

    
411
    @Override
412
    public T findByUuid(UUID uuid) throws DataAccessException {
413
        return this.findByUuid(uuid, INCLUDE_UNPUBLISHED);
414
    }
415

    
416
    protected T findByUuid(UUID uuid, boolean includeUnpublished) throws DataAccessException {
417
        Session session = getSession();
418
        Criteria crit = session.createCriteria(type);
419
        crit.add(Restrictions.eq("uuid", uuid));
420
        crit.addOrder(Order.desc("created"));
421
        if (IPublishable.class.isAssignableFrom(type) && !includeUnpublished) {
422
            crit.add(Restrictions.eq("publish", Boolean.TRUE));
423
        }
424

    
425
        @SuppressWarnings("unchecked")
426
        List<T> results = crit.list();
427
        Set<T> resultSet = new HashSet<>();
428
        resultSet.addAll(results);
429
        if (resultSet.isEmpty()) {
430
            return null;
431
        } else {
432
            if (resultSet.size() > 1) {
433
                logger.error("findByUuid() delivers more than one result for UUID: " + uuid);
434
            }
435
            return results.get(0);
436
        }
437
    }
438

    
439
    @Override
440
    public T findByUuidWithoutFlush(UUID uuid) throws DataAccessException {
441
        Session session = getSession();
442
        FlushMode currentFlushMode = session.getFlushMode();
443
        try {
444
            // set flush mode to manual so that the session does not flush
445
            // when before performing the query
446
            session.setFlushMode(FlushMode.MANUAL);
447
            Criteria crit = session.createCriteria(type);
448
            crit.add(Restrictions.eq("uuid", uuid));
449
            crit.addOrder(Order.desc("created"));
450
            @SuppressWarnings("unchecked")
451
            List<T> results = crit.list();
452
            if (results.isEmpty()) {
453
                return null;
454
            } else {
455
                if (results.size() > 1) {
456
                    logger.error("findByUuid() delivers more than one result for UUID: " + uuid);
457
                }
458
                return results.get(0);
459
            }
460
        } finally {
461
            // set back the session flush mode
462
            if (currentFlushMode != null) {
463
                session.setFlushMode(currentFlushMode);
464
            }
465
        }
466
    }
467

    
468
    @Override
469
    public List<T> loadList(Collection<Integer> ids, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {
470

    
471
        if (ids.isEmpty()) {
472
            return new ArrayList<>(0);
473
        }
474

    
475
        Criteria criteria = prepareList(null, ids, null, null, orderHints, "id");
476

    
477
        if (logger.isDebugEnabled()) {
478
            logger.debug(criteria.toString());
479
        }
480

    
481
        @SuppressWarnings("unchecked")
482
        List<T> result = criteria.list();
483
        defaultBeanInitializer.initializeAll(result, propertyPaths);
484
        return result;
485
    }
486

    
487
    @Override
488
    public List<T> list(Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
489
            List<String> propertyPaths) throws DataAccessException {
490

    
491
        if (uuids == null || uuids.isEmpty()) {
492
            return new ArrayList<>();
493
        }
494

    
495
        Criteria criteria = prepareList(null, uuids, pageSize, pageNumber, orderHints, "uuid");
496
        @SuppressWarnings("unchecked")
497
        List<T> result = criteria.list();
498
        defaultBeanInitializer.initializeAll(result, propertyPaths);
499
        return result;
500
    }
501

    
502
    @Override
503
    public <S extends T> List<S> list(Class<S> clazz, Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
504
            List<String> propertyPaths) throws DataAccessException {
505

    
506
        if (uuids == null || uuids.isEmpty()) {
507
            return new ArrayList<>();
508
        }
509

    
510
        Criteria criteria = prepareList(clazz, uuids, pageSize, pageNumber, orderHints, "uuid");
511
        @SuppressWarnings("unchecked")
512
        List<S> result = criteria.list();
513
        defaultBeanInitializer.initializeAll(result, propertyPaths);
514
        return result;
515
    }
516

    
517
    /**
518
     * {@inheritDoc}
519
     */
520
    @Override
521
    public <S extends T> List<S> list(Class<S> type, List<Restriction<?>> restrictions, Integer limit, Integer start,
522
            List<OrderHint> orderHints, List<String> propertyPaths) {
523

    
524
        Criteria criteria = createCriteria(type, restrictions, false);
525

    
526
        addLimitAndStart(criteria, limit, start);
527
        addOrder(criteria, orderHints);
528

    
529
        @SuppressWarnings("unchecked")
530
        List<S> result = criteria.list();
531
        defaultBeanInitializer.initializeAll(result, propertyPaths);
532
        return result;
533
    }
534

    
535
    /**
536
     * @param restrictions
537
     * @param criteria
538
     */
539
    private void addRestrictions(List<Restriction<?>> restrictions, DetachedCriteria criteria) {
540

    
541
        if(restrictions == null || restrictions.isEmpty()){
542
            return ;
543
        }
544

    
545
        List<CriterionWithOperator> perProperty = new ArrayList<>(restrictions.size());
546
        Map<String, String> aliases = new HashMap<>();
547

    
548

    
549

    
550
        for(Restriction<?> restriction : restrictions){
551
            Collection<? extends Object> values = restriction.getValues();
552
            JoinType jointype = LEFTOUTER_OPS.contains(restriction.getOperator()) ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
553
            if(values != null && !values.isEmpty()){
554
                // ---
555
                String propertyPath = restriction.getPropertyName();
556
                String[] props =  propertyPath.split("\\.");
557
                String propertyName;
558
                if(props.length == 1){
559
                    // direct property of the base type of the criteria
560
                    propertyName = propertyPath;
561
                } else {
562
                    // create aliases if the propertyName is a dot separated property path
563
                    String aĺiasKey = jointype.name() + "_";
564
                    String aliasedProperty = null;
565
                    String alias = "";
566
                    for(int p = 0; p < props.length -1; p++){
567
                        aĺiasKey = aĺiasKey + (aĺiasKey.isEmpty() ? "" : ".") + props[p];
568
                        aliasedProperty = alias + (alias.isEmpty() ? "" : ".") + props[p];
569
                        if(!aliases.containsKey(aliasedProperty)){
570
                            alias = alias + (alias.isEmpty() ? "" : "_" ) + props[p];
571
                            aliases.put(aĺiasKey, alias);
572
                            criteria.createAlias(aliasedProperty, alias, jointype);
573
                            if(logger.isDebugEnabled()){
574
                                logger.debug("addRestrictions() alias created with aliasKey " + aĺiasKey + " => " + aliasedProperty + " as " + alias);
575
                            }
576
                        }
577
                    }
578
                    propertyName = alias + "." + props[props.length -1];
579
                }
580
                // ---
581
                Criterion[] predicates = new Criterion[values.size()];
582
                int i = 0;
583
                for(Object v : values){
584
                    Criterion criterion = createRestriction(propertyName, v, restriction.getMatchMode());
585
                    if(restriction.isNot()){
586
                        if(props.length > 1){
587
                            criterion = Restrictions.or(Restrictions.not(criterion), Restrictions.isNull(propertyName));
588
                        } else {
589
                            criterion = Restrictions.not(criterion);
590
                        }
591
                    }
592
                    predicates[i++] = criterion;
593
                    if(logger.isDebugEnabled()){
594
                        logger.debug("addRestrictions() predicate with " + propertyName + " " + (restriction.getMatchMode() == null ? "=" : restriction.getMatchMode().name()) + " " + v.toString());
595
                    }
596
                }
597
                if(restriction.getOperator() == Operator.AND_NOT){
598
                    perProperty.add(new CriterionWithOperator(restriction.getOperator(), Restrictions.and(predicates)));
599
                } else {
600
                    perProperty.add(new CriterionWithOperator(restriction.getOperator(), Restrictions.or(predicates)));
601
                }
602
            } // check has values
603
        } // loop over restrictions
604

    
605
        Restriction.Operator firstOperator = null;
606
        if(!perProperty.isEmpty()){
607
            LogicalExpression logicalExpression = null;
608
            for(CriterionWithOperator cwo : perProperty){
609
                if(logicalExpression == null){
610
                    firstOperator = cwo.operator;
611
                    logicalExpression = Restrictions.and(Restrictions.sqlRestriction("1=1"), cwo.criterion);
612
                } else {
613
                    switch(cwo.operator){
614
                        case AND:
615
                        case AND_NOT:
616
                            logicalExpression = Restrictions.and(logicalExpression, cwo.criterion);
617
                            break;
618
                        case OR:
619
                        case OR_NOT:
620
                            logicalExpression = Restrictions.or(logicalExpression, cwo.criterion);
621
                            break;
622
                        default:
623
                            throw new RuntimeException("Unsupported Operator");
624
                    }
625
                }
626

    
627
            }
628

    
629

    
630
            criteria.add(logicalExpression);
631
//            if(firstOperator == Operator.OR){
632
//                // OR
633
//            } else {
634
//                // AND
635
//                criteria.add(Restrictions.and(queryStringCriterion, logicalExpression));
636
//            }
637
        }
638
        if(logger.isDebugEnabled()){
639
            logger.debug("addRestrictions() final criteria: " + criteria.toString());
640
        }
641
    }
642

    
643
    /**
644
     * @param propertyName
645
     * @param value
646
     * @param matchMode
647
     *            is only applied if the <code>value</code> is a
648
     *            <code>String</code> object
649
     * @param criteria
650
     * @return
651
     */
652
    private Criterion createRestriction(String propertyName, Object value, MatchMode matchMode) {
653

    
654
        Criterion restriction;
655
        if (value == null) {
656
            if (logger.isDebugEnabled()) {
657
                logger.debug("createRestriction() " + propertyName + " is null ");
658
            }
659
            restriction = Restrictions.isNull(propertyName);
660
        } else if (matchMode == null || !(value instanceof String)) {
661
            if (logger.isDebugEnabled()) {
662
                logger.debug("createRestriction() " + propertyName + " = " + value.toString());
663
            }
664
            restriction = Restrictions.eq(propertyName, value);
665
        } else {
666
            String queryString = (String) value;
667
            if (logger.isDebugEnabled()) {
668
                logger.debug("createRestriction() " + propertyName + " " + matchMode.getMatchOperator() + " "
669
                        + matchMode.queryStringFrom(queryString));
670
            }
671
            switch(matchMode){
672
            case BEGINNING:
673
                restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.START);
674
                break;
675
            case END:
676
                restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.END);
677
                break;
678
            case LIKE:
679
                restriction = Restrictions.ilike(propertyName, matchMode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.ANYWHERE);
680
                break;
681
            case EXACT:
682
                restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.EXACT);
683
                break;
684
            case ANYWHERE:
685
                restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.ANYWHERE);
686
                break;
687
            default:
688
                throw new RuntimeException("Unknown MatchMode: " + matchMode.name());
689
            }
690
        }
691
        return restriction;
692
    }
693

    
694
    /**
695
     * {@inheritDoc}
696
     */
697
    @Override
698
    public long count(Class<? extends T> type, List<Restriction<?>> restrictions) {
699

    
700
        Criteria criteria = createCriteria(type, restrictions, false);
701

    
702
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
703

    
704
        return (Long) criteria.uniqueResult();
705

    
706
    }
707

    
708
    /**
709
     * @param uuids
710
     * @param pageSize
711
     * @param pageNumber
712
     * @param orderHints
713
     * @param propertyName
714
     * @return
715
     */
716
    private Criteria prepareList(Class<? extends T> clazz, Collection<?> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
717
            String propertyName) {
718
        if (clazz == null){
719
            clazz = type;
720
        }
721
        Criteria criteria = getSession().createCriteria(clazz);
722
        criteria.add(Restrictions.in(propertyName, uuids));
723

    
724
        if (pageSize != null) {
725
            criteria.setMaxResults(pageSize);
726
            if (pageNumber != null) {
727
                criteria.setFirstResult(pageNumber * pageSize);
728
            } else {
729
                criteria.setFirstResult(0);
730
            }
731
        }
732

    
733
        if (orderHints == null) {
734
            orderHints = OrderHint.defaultOrderHintsFor(type);
735
        }
736
        addOrder(criteria, orderHints);
737
        return criteria;
738
    }
739

    
740
    /**
741
     * @param clazz
742
     * @return
743
     */
744
    private Criteria criterionForType(Class<? extends T> clazz) {
745
        return  getSession().createCriteria(entityType(clazz));
746
    }
747

    
748
    protected Class<? extends T> entityType(Class<? extends T> clazz){
749
        if (clazz != null) {
750
            return clazz;
751
        } else {
752
            return type;
753
        }
754
    }
755

    
756
    @Override
757
    public T load(UUID uuid) {
758
        T bean = findByUuid(uuid);
759
        if (bean == null) {
760
            return null;
761
        }
762
        defaultBeanInitializer.load(bean);
763

    
764
        return bean;
765
    }
766

    
767
    @Override
768
    public T load(int id, List<String> propertyPaths) {
769
        T bean = findById(id);
770
        if (bean == null) {
771
            return bean;
772
        }
773
        defaultBeanInitializer.initialize(bean, propertyPaths);
774

    
775
        return bean;
776
    }
777

    
778
    @Override
779
    public T load(UUID uuid, List<String> propertyPaths) {
780
        return this.load(uuid, INCLUDE_UNPUBLISHED, propertyPaths);
781
    }
782

    
783
    protected T load(UUID uuid, boolean includeUnpublished, List<String> propertyPaths) {
784
        T bean = findByUuid(uuid, includeUnpublished);
785
        if (bean == null) {
786
            return bean;
787
        }
788
        defaultBeanInitializer.initialize(bean, propertyPaths);
789

    
790
        return bean;
791
    }
792

    
793
    @Override
794
    public Boolean exists(UUID uuid) {
795
        if (findByUuid(uuid) == null) {
796
            return false;
797
        }
798
        return true;
799
    }
800

    
801
    @Override
802
    public long count() {
803
        return count(type);
804
    }
805

    
806
    @Override
807
    public long count(Class<? extends T> clazz) {
808
        Session session = getSession();
809
        Criteria criteria = null;
810
        if (clazz == null) {
811
            criteria = session.createCriteria(type);
812
        } else {
813
            criteria = session.createCriteria(clazz);
814
        }
815
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
816

    
817
        // since hibernate 4 (or so) uniqueResult returns Long, not Integer,
818
        // therefore needs
819
        // to be casted. Think about returning long rather then int!
820
        return (long) criteria.uniqueResult();
821
    }
822

    
823
    @Override
824
    public List<T> list(Integer limit, Integer start) {
825
        return list(limit, start, null);
826
    }
827

    
828
    @Override
829
    public List<Object[]> group(Class<? extends T> clazz, Integer limit, Integer start, List<Grouping> groups,
830
            List<String> propertyPaths) {
831

    
832
        Criteria criteria = null;
833
        criteria = criterionForType(clazz);
834

    
835
        addGroups(criteria, groups);
836

    
837
        if (limit != null) {
838
            criteria.setFirstResult(start);
839
            criteria.setMaxResults(limit);
840
        }
841

    
842
        @SuppressWarnings("unchecked")
843
        List<Object[]> result = criteria.list();
844

    
845
        if (propertyPaths != null && !propertyPaths.isEmpty()) {
846
            for (Object[] objects : result) {
847
                defaultBeanInitializer.initialize(objects[0], propertyPaths);
848
            }
849
        }
850

    
851
        return result;
852
    }
853

    
854
    protected void countGroups(DetachedCriteria criteria, List<Grouping> groups) {
855
        if (groups != null) {
856

    
857
            Map<String, String> aliases = new HashMap<String, String>();
858

    
859
            for (Grouping grouping : groups) {
860
                if (grouping.getAssociatedObj() != null) {
861
                    String alias = null;
862
                    if ((alias = aliases.get(grouping.getAssociatedObj())) == null) {
863
                        alias = grouping.getAssociatedObjectAlias();
864
                        aliases.put(grouping.getAssociatedObj(), alias);
865
                        criteria.createAlias(grouping.getAssociatedObj(), alias);
866
                    }
867
                }
868
            }
869

    
870
            ProjectionList projectionList = Projections.projectionList();
871

    
872
            for (Grouping grouping : groups) {
873
                grouping.addProjection(projectionList);
874
            }
875
            criteria.setProjection(projectionList);
876
        }
877
    }
878

    
879
    protected void addGroups(Criteria criteria, List<Grouping> groups) {
880
        if (groups != null) {
881

    
882
            Map<String, String> aliases = new HashMap<String, String>();
883

    
884
            for (Grouping grouping : groups) {
885
                if (grouping.getAssociatedObj() != null) {
886
                    String alias = null;
887
                    if ((alias = aliases.get(grouping.getAssociatedObj())) == null) {
888
                        alias = grouping.getAssociatedObjectAlias();
889
                        aliases.put(grouping.getAssociatedObj(), alias);
890
                        criteria.createAlias(grouping.getAssociatedObj(), alias);
891
                    }
892
                }
893
            }
894

    
895
            ProjectionList projectionList = Projections.projectionList();
896

    
897
            for (Grouping grouping : groups) {
898
                grouping.addProjection(projectionList);
899
            }
900
            criteria.setProjection(projectionList);
901

    
902
            for (Grouping grouping : groups) {
903
                grouping.addOrder(criteria);
904

    
905
            }
906
        }
907
    }
908

    
909
    @Override
910
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {
911
        return list(limit, start, orderHints, null);
912
    }
913

    
914
    @Override
915
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
916
        Criteria criteria = getSession().createCriteria(type);
917
        if (limit != null) {
918
            criteria.setFirstResult(start);
919
            criteria.setMaxResults(limit);
920
        }
921

    
922
        addOrder(criteria, orderHints);
923
        @SuppressWarnings("unchecked")
924
        List<T> results = criteria.list();
925

    
926
        defaultBeanInitializer.initializeAll(results, propertyPaths);
927
        return results;
928
    }
929

    
930
    @Override
931
    public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints,
932
            List<String> propertyPaths) {
933
        Criteria criteria = null;
934
        if (clazz == null) {
935
            criteria = getSession().createCriteria(type);
936
        } else {
937
            criteria = getSession().createCriteria(clazz);
938
        }
939

    
940
        addLimitAndStart(criteria, limit, start);
941

    
942
        addOrder(criteria, orderHints);
943

    
944
        @SuppressWarnings("unchecked")
945
        List<S> results = criteria.list();
946

    
947
        defaultBeanInitializer.initializeAll(results, propertyPaths);
948
        return results;
949
    }
950

    
951
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints) {
952
        return list(type, limit, start, orderHints, null);
953
    }
954

    
955
    @Override
956
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start) {
957
        return list(type, limit, start, null, null);
958
    }
959

    
960
    @Override
961
    public Class<T> getType() {
962
        return type;
963
    }
964

    
965
    protected void setPagingParameter(Query query, Integer pageSize, Integer pageIndex) {
966
        if (pageSize != null) {
967
            query.setMaxResults(pageSize);
968
            if (pageIndex != null) {
969
                query.setFirstResult(pageIndex * pageSize);
970
            } else {
971
                query.setFirstResult(0);
972
            }
973
        }
974
    }
975

    
976
    protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageIndex) {
977
        if (pageSize != null) {
978
            query.setMaxResults(pageSize);
979
            if (pageIndex != null) {
980
                query.setFirstResult(pageIndex * pageSize);
981
            } else {
982
                query.setFirstResult(0);
983
            }
984
        }
985
    }
986

    
987
    @Override
988
    public long count(T example, Set<String> includeProperties) {
989
        Criteria criteria = getSession().createCriteria(example.getClass());
990
        addExample(criteria, example, includeProperties);
991

    
992
        criteria.setProjection(Projections.rowCount());
993
        return (Long) criteria.uniqueResult();
994
    }
995

    
996
    protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {
997
        if (includeProperties != null && !includeProperties.isEmpty()) {
998
            criteria.add(Example.create(example).setPropertySelector(new PropertySelectorImpl(includeProperties)));
999
            ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(example.getClass());
1000
            for (String property : includeProperties) {
1001
                Type type = classMetadata.getPropertyType(property);
1002
                if (type.isEntityType()) {
1003
                    try {
1004
                        Field field = ReflectionUtils.findField(example.getClass(), property);
1005
                        field.setAccessible(true);
1006
                        Object value = field.get(example);
1007
                        if (value != null) {
1008
                            criteria.add(Restrictions.eq(property, value));
1009
                        } else {
1010
                            criteria.add(Restrictions.isNull(property));
1011
                        }
1012
                    } catch (SecurityException se) {
1013
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,
1014
                                se);
1015
                    } catch (HibernateException he) {
1016
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,
1017
                                he);
1018
                    } catch (IllegalArgumentException iae) {
1019
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,
1020
                                iae);
1021
                    } catch (IllegalAccessException ie) {
1022
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,
1023
                                ie);
1024
                    }
1025
                }
1026
            }
1027
        } else {
1028
            criteria.add(Example.create(example));
1029
        }
1030
    }
1031

    
1032
    /**
1033
     *
1034
     * NOTE: We can't reuse
1035
     * {@link #list(Class, String, Object, MatchMode, Integer, Integer, List, List)
1036
     * here due to different default behavior of the <code>matchmode</code>
1037
     * parameter.
1038
     *
1039
     * @param clazz
1040
     * @param param
1041
     * @param queryString
1042
     * @param matchmode
1043
     * @param criterion
1044
     * @param pageSize
1045
     * @param pageNumber
1046
     * @param orderHints
1047
     * @param propertyPaths
1048
     * @return
1049
     */
1050
    @Override
1051
    public <S extends T> List<S> findByParam(Class<S> clazz, String param, String queryString, MatchMode matchmode,
1052
            List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
1053
            List<String> propertyPaths) {
1054
        Set<String> stringSet = new HashSet<>();
1055
        stringSet.add(param);
1056
        return this.findByParam(clazz, stringSet, queryString, matchmode,
1057
                criterion, pageSize, pageNumber, orderHints,
1058
                propertyPaths);
1059
    }
1060

    
1061
    @Override
1062
    public <S extends T> List<S> findByParam(Class<S> clazz, Set<String> params, String queryString, MatchMode matchmode,
1063
            List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,
1064
            List<String> propertyPaths) {
1065

    
1066
        Criteria criteria = criterionForType(clazz);
1067

    
1068
        if (queryString != null) {
1069
            Set<Criterion> criterions = new HashSet<>();
1070
            for (String param: params){
1071
                Criterion crit;
1072
                if (matchmode == null) {
1073
                     crit = Restrictions.ilike(param, queryString);
1074
                } else if (matchmode == MatchMode.BEGINNING) {
1075
                     crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START);
1076
                } else if (matchmode == MatchMode.END) {
1077
                    crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END);
1078
                } else if (matchmode == MatchMode.EXACT) {
1079
                    crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT);
1080
                } else {
1081
                    crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE);
1082
                }
1083
                criterions.add(crit);
1084
            }
1085
            if (criterions.size()>1){
1086
                Iterator<Criterion> critIterator = criterions.iterator();
1087
                Disjunction disjunction = Restrictions.disjunction();
1088
                while (critIterator.hasNext()){
1089
                    disjunction.add(critIterator.next());
1090
                }
1091

    
1092
                criteria.add(disjunction);
1093

    
1094
            }else{
1095
                if (!criterions.isEmpty()){
1096
                    criteria.add(criterions.iterator().next());
1097
                }
1098
            }
1099

    
1100
        }
1101

    
1102
        addCriteria(criteria, criterion);
1103

    
1104
        if (pageSize != null) {
1105
            criteria.setMaxResults(pageSize);
1106
            if (pageNumber != null) {
1107
                criteria.setFirstResult(pageNumber * pageSize);
1108
            } else {
1109
                criteria.setFirstResult(0);
1110
            }
1111
        }
1112

    
1113
        addOrder(criteria, orderHints);
1114

    
1115
        @SuppressWarnings("unchecked")
1116
        List<S> result = criteria.list();
1117
        defaultBeanInitializer.initializeAll(result, propertyPaths);
1118
        return result;
1119
    }
1120

    
1121
    /**
1122
     *
1123
     * @param clazz
1124
     * @param param
1125
     * @param queryString
1126
     * @param matchmode
1127
     * @param criterion
1128
     * @return
1129
     */
1130
    @Override
1131
    public long countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode,
1132
            List<Criterion> criterion) {
1133

    
1134
        Criteria criteria = null;
1135

    
1136
        criteria = criterionForType(clazz);
1137

    
1138
        if (queryString != null) {
1139
            if (matchmode == null) {
1140
                criteria.add(Restrictions.ilike(param, queryString));
1141
            } else if (matchmode == MatchMode.BEGINNING) {
1142
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
1143
            } else if (matchmode == MatchMode.END) {
1144
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
1145
            } else if (matchmode == MatchMode.EXACT) {
1146
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
1147
            } else {
1148
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
1149
            }
1150
        }
1151

    
1152
        addCriteria(criteria, criterion);
1153

    
1154
        criteria.setProjection(Projections.rowCount());
1155

    
1156
        return (Long) criteria.uniqueResult();
1157
    }
1158

    
1159
    /**
1160
     * Creates a criteria query for the CDM <code>type</code> either for counting or listing matching entities.
1161
     * <p>
1162
     * The set of matching entities can be restricted by passing a list  of {@link Restriction} objects.
1163
     * Restrictions can logically combined:
1164
     <pre>
1165
       Arrays.asList(
1166
           new Restriction<String>("titleCache", MatchMode.ANYWHERE, "foo"),
1167
           new Restriction<String>("institute.name", Operator.OR, MatchMode.BEGINNING, "Bar")
1168
       );
1169
     </pre>
1170
     * The first Restriction in the example above by default has the <code>Operator.AND</code> which will be
1171
     * ignored since this is the first restriction. The <code>Operator</code> of further restrictions in the
1172
     * list are used to combine with the previous restriction.
1173
     *
1174
     * @param type
1175
     * @param restrictions
1176
     * @param doCount
1177
     * @return
1178
     */
1179
    protected Criteria createCriteria(Class<? extends T> type, List<Restriction<?>> restrictions, boolean doCount) {
1180

    
1181
        DetachedCriteria idsOnlyCriteria = DetachedCriteria.forClass(entityType(type));
1182
        idsOnlyCriteria.setProjection(Projections.distinct(Projections.id()));
1183

    
1184
        addRestrictions(restrictions, idsOnlyCriteria);
1185

    
1186
        Criteria criteria = criterionForType(type);
1187
        criteria.add(Subqueries.propertyIn("id", idsOnlyCriteria));
1188

    
1189
        if(doCount){
1190
            criteria.setProjection(Projections.rowCount());
1191
        } else {
1192
            idsOnlyCriteria.setProjection(Projections.distinct(Projections.property("id")));
1193
        }
1194

    
1195
        return criteria;
1196
    }
1197

    
1198

    
1199
    @Override
1200
    public <S extends T> List<S> findByParamWithRestrictions(Class<S> clazz, String param, String queryString,
1201
            MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber,
1202
            List<OrderHint> orderHints, List<String> propertyPaths) {
1203

    
1204
        List<Restriction<?>> allRestrictions = new ArrayList<>();
1205
        allRestrictions.add(new Restriction<String>(param, matchmode, queryString));
1206
        if(restrictions != null){
1207
            allRestrictions.addAll(restrictions);
1208
        }
1209
        Criteria criteria = createCriteria(clazz, allRestrictions, false);
1210

    
1211
        if (pageSize != null) {
1212
            criteria.setMaxResults(pageSize);
1213
            if (pageNumber != null) {
1214
                criteria.setFirstResult(pageNumber * pageSize);
1215
            } else {
1216
                criteria.setFirstResult(0);
1217
            }
1218
        }
1219

    
1220
        addOrder(criteria, orderHints);
1221

    
1222
        @SuppressWarnings("unchecked")
1223
        List<S> result = criteria.list();
1224
        defaultBeanInitializer.initializeAll(result, propertyPaths);
1225
        return result;
1226

    
1227
    }
1228

    
1229
    @Override
1230
    public long countByParamWithRestrictions(Class<? extends T> clazz, String param, String queryString,
1231
            MatchMode matchmode, List<Restriction<?>> restrictions) {
1232

    
1233
        List<Restriction<?>> allRestrictions = new ArrayList<>();
1234
        allRestrictions.add(new Restriction<String>(param, matchmode, queryString));
1235
        if(restrictions != null){
1236
            allRestrictions.addAll(restrictions);
1237
        }
1238
        Criteria criteria = createCriteria(clazz, allRestrictions, true);
1239

    
1240
        return (Long) criteria.uniqueResult();
1241
    }
1242

    
1243
    @Override
1244
    public <S extends T> List<S> list(S example, Set<String> includeProperties, Integer limit, Integer start,
1245
            List<OrderHint> orderHints, List<String> propertyPaths) {
1246
        Criteria criteria = getSession().createCriteria(example.getClass());
1247
        addExample(criteria, example, includeProperties);
1248

    
1249
        addLimitAndStart(criteria, limit, start);
1250

    
1251
        addOrder(criteria, orderHints);
1252

    
1253
        @SuppressWarnings("unchecked")
1254
        List<S> results = criteria.list();
1255
        defaultBeanInitializer.initializeAll(results, propertyPaths);
1256
        return results;
1257
    }
1258

    
1259
    private class PropertySelectorImpl implements PropertySelector {
1260

    
1261
        private final Set<String> includeProperties;
1262
        /**
1263
         *
1264
         */
1265
        private static final long serialVersionUID = -3175311800911570546L;
1266

    
1267
        public PropertySelectorImpl(Set<String> includeProperties) {
1268
            this.includeProperties = includeProperties;
1269
        }
1270

    
1271
        @Override
1272
        public boolean include(Object propertyValue, String propertyName, Type type) {
1273
            if (includeProperties.contains(propertyName)) {
1274
                return true;
1275
            } else {
1276
                return false;
1277
            }
1278
        }
1279

    
1280
    }
1281

    
1282
    private class CriterionWithOperator {
1283

    
1284
        Restriction.Operator operator;
1285
        Criterion criterion;
1286

    
1287

    
1288
        public CriterionWithOperator(Operator operator, Criterion criterion) {
1289
            super();
1290
            this.operator = operator;
1291
            this.criterion = criterion;
1292
        }
1293

    
1294

    
1295
    }
1296

    
1297
    /**
1298
     * Returns a Criteria for the given {@link Class class} or, if
1299
     * <code>null</code>, for the base {@link Class class} of this DAO.
1300
     *
1301
     * @param clazz
1302
     * @return the Criteria
1303
     */
1304
    protected Criteria getCriteria(Class<? extends CdmBase> clazz) {
1305
        Criteria criteria = null;
1306
        if (clazz == null) {
1307
            criteria = getSession().createCriteria(type);
1308
        } else {
1309
            criteria = getSession().createCriteria(clazz);
1310
        }
1311
        return criteria;
1312
    }
1313

    
1314
    /**
1315
     * @param clazz
1316
     * @param auditEvent
1317
     * @return
1318
     */
1319
    protected AuditQuery makeAuditQuery(Class<? extends CdmBase> clazz, AuditEvent auditEvent) {
1320
        AuditQuery query = null;
1321

    
1322
        if (clazz == null) {
1323
            query = getAuditReader().createQuery().forEntitiesAtRevision(type, auditEvent.getRevisionNumber());
1324
        } else {
1325
            query = getAuditReader().createQuery().forEntitiesAtRevision(clazz, auditEvent.getRevisionNumber());
1326
        }
1327
        return query;
1328
    }
1329

    
1330
    protected AuditReader getAuditReader() {
1331
        return AuditReaderFactory.get(getSession());
1332
    }
1333
}
(3-3/18)