Project

General

Profile

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

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

    
22
import org.apache.log4j.Logger;
23
import org.apache.lucene.search.Sort;
24
import org.apache.lucene.search.SortField;
25
import org.apache.lucene.util.Version;
26
import org.hibernate.Criteria;
27
import org.hibernate.HibernateException;
28
import org.hibernate.LockMode;
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.Example;
35
import org.hibernate.criterion.Example.PropertySelector;
36
import org.hibernate.criterion.Order;
37
import org.hibernate.criterion.ProjectionList;
38
import org.hibernate.criterion.Projections;
39
import org.hibernate.criterion.Restrictions;
40
import org.hibernate.envers.query.AuditQuery;
41
import org.hibernate.metadata.ClassMetadata;
42
import org.hibernate.search.FullTextQuery;
43
import org.hibernate.type.Type;
44
import org.joda.time.DateTime;
45
import org.springframework.beans.factory.annotation.Autowired;
46
import org.springframework.dao.DataAccessException;
47
import org.springframework.dao.InvalidDataAccessApiUsageException;
48
import org.springframework.security.core.Authentication;
49
import org.springframework.security.core.context.SecurityContextHolder;
50
import org.springframework.stereotype.Repository;
51
import org.springframework.util.ReflectionUtils;
52

    
53
import eu.etaxonomy.cdm.config.Configuration;
54
import eu.etaxonomy.cdm.model.common.CdmBase;
55
import eu.etaxonomy.cdm.model.common.User;
56
import eu.etaxonomy.cdm.model.common.VersionableEntity;
57
import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
58
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
59
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadata;
60
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadataFactory;
61
import eu.etaxonomy.cdm.persistence.query.Grouping;
62
import eu.etaxonomy.cdm.persistence.query.MatchMode;
63
import eu.etaxonomy.cdm.persistence.query.OrderHint;
64

    
65

    
66
/**
67
 * @author a.mueller
68
 * FIXME CdmEntityDaoBase is abstract, can it be annotated with @Repository?
69
 */
70
@Repository
71
public abstract class CdmEntityDaoBase<T extends CdmBase> extends DaoBase implements ICdmEntityDao<T> {
72
    private static final Logger logger = Logger.getLogger(CdmEntityDaoBase.class);
73

    
74
    protected int flushAfterNo = 1000; //large numbers may cause synchronisation errors when commiting the session !!
75

    
76
    protected Class<T> type;
77

    
78
    protected Version version = Configuration.luceneVersion;
79

    
80
    @Autowired
81
//	@Qualifier("defaultBeanInitializer")
82
    protected IBeanInitializer defaultBeanInitializer;
83

    
84
    public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer) {
85
        this.defaultBeanInitializer = defaultBeanInitializer;
86
    }
87

    
88
    @Autowired
89
    private ReferringObjectMetadataFactory referringObjectMetadataFactory;
90

    
91

    
92
    public CdmEntityDaoBase(Class<T> type){
93
        this.type = type;
94
        logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");
95
    }
96

    
97
    @Override
98
    public void lock(T t, LockMode lockMode) {
99
        getSession().lock(t, lockMode);
100
    }
101

    
102
    @Override
103
    public void refresh(T t, LockMode lockMode, List<String> propertyPaths) {
104
        getSession().refresh(t, lockMode);
105
        defaultBeanInitializer.initialize(t, propertyPaths);
106
    }
107

    
108
    //TODO this method should be moved to a concrete class (not typed)
109
    public UUID saveCdmObj(CdmBase cdmObj) throws DataAccessException  {
110
        getSession().saveOrUpdate(cdmObj);
111
        return cdmObj.getUuid();
112
    }
113

    
114
    //TODO: Replace saveCdmObj() by saveCdmObject_
115
    private UUID saveCdmObject_(T cdmObj){
116
        getSession().saveOrUpdate(cdmObj);
117
        return cdmObj.getUuid();
118
    }
119

    
120
    //TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of ServiceBase.saveCdmObjectAll()?
121
    //TODO: why does this use saveCdmObject_ which actually savesOrUpdateds data ?
122
    @Override
123
    public Map<UUID, T> saveAll(Collection<T> cdmObjCollection){
124
        int types = cdmObjCollection.getClass().getTypeParameters().length;
125
        if (types > 0){
126
            if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}
127
        }
128

    
129
        Map<UUID, T> resultMap = new HashMap<UUID, T>();
130
        Iterator<T> iterator = cdmObjCollection.iterator();
131
        int i = 0;
132
        while(iterator.hasNext()){
133
            if ( ( (i % 2000) == 0) && (i > 0)   ){logger.debug("Saved " + i + " objects" );}
134
            T cdmObj = iterator.next();
135
            UUID uuid = saveCdmObject_(cdmObj);
136
            if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
137
            resultMap.put(uuid, cdmObj);
138
            i++;
139
            if ( (i % flushAfterNo) == 0){
140
                try{
141
                    if (logger.isDebugEnabled()){logger.debug("flush");}
142
                    flush();
143
                }catch(Exception e){
144
                    logger.error("An exception occurred when trying to flush data");
145
                    e.printStackTrace();
146
                    throw new RuntimeException(e);
147
                }
148
            }
149
        }
150

    
151
        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
152
        return resultMap;
153
    }
154

    
155
    private UUID saveOrUpdateCdmObject(T cdmObj){
156
        getSession().saveOrUpdate(cdmObj);
157
        return cdmObj.getUuid();
158
    }
159

    
160
    @Override
161
    public Map<UUID, T> saveOrUpdateAll(Collection<T> cdmObjCollection){
162
        int types = cdmObjCollection.getClass().getTypeParameters().length;
163
        if (types > 0){
164
            if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}
165
        }
166

    
167
        Map<UUID, T> resultMap = new HashMap<UUID, T>();
168
        Iterator<T> iterator = cdmObjCollection.iterator();
169
        int i = 0;
170
        while(iterator.hasNext()){
171
            if ( ( (i % 2000) == 0) && (i > 0)   ){logger.debug("Saved " + i + " objects" );}
172
            T cdmObj = iterator.next();
173
            UUID uuid = saveOrUpdateCdmObject(cdmObj);
174
            if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
175
            resultMap.put(uuid, cdmObj);
176
            i++;
177
            if ( (i % flushAfterNo) == 0){
178
                try{
179
                    if (logger.isDebugEnabled()){logger.debug("flush");}
180
                    flush();
181
                }catch(Exception e){
182
                    logger.error("An exception occurred when trying to flush data");
183
                    e.printStackTrace();
184
                    throw new RuntimeException(e);
185
                }
186
            }
187
        }
188

    
189
        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
190
        return resultMap;
191
    }
192

    
193

    
194

    
195

    
196
    @Override
197
    public T replace(T x, T y) {
198
        if(x.equals(y)) {
199
            return y;
200
        }
201

    
202
        Class commonClass = x.getClass();
203
        if(y != null) {
204
            while(!commonClass.isAssignableFrom(y.getClass())) {
205
                if(commonClass.equals(type)) {
206
                    throw new RuntimeException();
207
                }
208
                commonClass = commonClass.getSuperclass();
209
            }
210
        }
211

    
212
        getSession().merge(x);
213

    
214
        Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());
215

    
216
        for(ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {
217

    
218
          List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x, getSession());
219

    
220
          for(CdmBase referringObject : referringObjects) {
221
            try {
222
                referringObjectMetadata.replace(referringObject,x,y);
223
                getSession().update(referringObject);
224

    
225
            } catch (IllegalArgumentException e) {
226
                throw new RuntimeException(e.getMessage(),e);
227
            } catch (IllegalAccessException e) {
228
                throw new RuntimeException(e.getMessage(),e);
229
            }
230
          }
231
        }
232
        return y;
233
    }
234

    
235
    @Override
236
    public Session getSession() throws DataAccessException {
237
        return super.getSession();
238
    }
239

    
240
    @Override
241
    public void clear() throws DataAccessException {
242
        Session session = getSession();
243
        session.clear();
244
        if (logger.isDebugEnabled()){logger.debug("dao clear end");}
245
    }
246

    
247
    @Override
248
    public T merge(T transientObject) throws DataAccessException {
249
        Session session = getSession();
250
        T persistentObject = (T)session.merge(transientObject);
251
        if (logger.isDebugEnabled()){logger.debug("dao merge end");}
252
        return persistentObject;
253
    }
254

    
255
    @Override
256
    public UUID saveOrUpdate(T transientObject) throws DataAccessException  {
257
        if (transientObject == null){
258
        	logger.warn("Object to save should not be null. NOP");
259
        	return null;
260
        }
261
    	try {
262
            if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate start...");}
263
            if (logger.isDebugEnabled()){logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:" + transientObject.getId() + ", UUID: " + transientObject.getUuid()) ;}
264
            Session session = getSession();
265
            if(transientObject.getId() != 0 && VersionableEntity.class.isAssignableFrom(transientObject.getClass())) {
266
                VersionableEntity versionableEntity = (VersionableEntity)transientObject;
267
                versionableEntity.setUpdated(new DateTime());
268
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
269
                if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
270
                  User user = (User)authentication.getPrincipal();
271
                  versionableEntity.setUpdatedBy(user);
272
                }
273
            }
274
            session.saveOrUpdate(transientObject);
275
            if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}
276
            return transientObject.getUuid();
277
        } catch (NonUniqueObjectException e) {
278
            logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj)");
279
            logger.error(e.getIdentifier());
280
            logger.error(e.getEntityName());
281
            logger.error(e.getMessage());
282

    
283
            e.printStackTrace();
284
            throw e;
285
        } catch (HibernateException e) {
286

    
287
            e.printStackTrace();
288
            throw e;
289
        }
290
    }
291

    
292
    @Override
293
    public UUID save(T newInstance) throws DataAccessException {
294
        if (newInstance == null){
295
        	logger.warn("Object to save should not be null. NOP");
296
        	return null;
297
        }
298
    	getSession().save(newInstance);
299
        return newInstance.getUuid();
300
    }
301

    
302
    @Override
303
    public UUID update(T transientObject) throws DataAccessException {
304
        if (transientObject == null){
305
        	logger.warn("Object to update should not be null. NOP");
306
        	return null;
307
        }
308
    	getSession().update(transientObject);
309
        return transientObject.getUuid();
310
    }
311

    
312
    @Override
313
    public UUID refresh(T persistentObject) throws DataAccessException {
314
        getSession().refresh(persistentObject);
315
        return persistentObject.getUuid();
316
    }
317

    
318
    @Override
319
    public UUID delete(T persistentObject) throws DataAccessException {
320
        if (persistentObject == null){
321
            logger.warn(type.getName() + " was 'null'");
322
            return null;
323
        }
324

    
325
        // Merge the object in if it is detached
326
        //
327
        // I think this is preferable to catching lazy initialization errors
328
        // as that solution only swallows and hides the exception, but doesn't
329
        // actually solve it.
330
        getSession().merge(persistentObject);
331
        getSession().delete(persistentObject);
332
        return persistentObject.getUuid();
333
    }
334

    
335
    @Override
336
    public T findById(int id) throws DataAccessException {
337
        return (T) getSession().get(type, id);
338
    }
339

    
340

    
341
    @Override
342
    public T findByUuid(UUID uuid) throws DataAccessException{
343
        Session session = getSession();
344
        Criteria crit = session.createCriteria(type);
345
        crit.add(Restrictions.eq("uuid", uuid));
346
        crit.addOrder(Order.desc("created"));
347
        List<T> results = crit.list();
348
        if (results.isEmpty()){
349
            return null;
350
        }else{
351
            if(results.size() > 1){
352
                logger.error("findByUuid() delivers more than one result for UUID: " + uuid);
353
            }
354
            return results.get(0);
355
        }
356
    }
357

    
358
    @Override
359
    public List<T> listByIds(Collection<Integer> ids,  Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {
360

    
361
        if (ids.isEmpty()) {
362
            return new ArrayList<T>(0);
363
        }
364

    
365
        Criteria criteria = prepareList(ids, pageSize, pageNumber, orderHints, "id");
366

    
367
        logger.debug(criteria.toString());
368

    
369
         List<T> result = criteria.list();
370
         defaultBeanInitializer.initializeAll(result, propertyPaths);
371
         return result;
372
     }
373

    
374

    
375
    @Override
376
    public List<T> list(Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {
377

    
378
       Criteria criteria = prepareList(uuids, pageSize, pageNumber, orderHints, "uuid");
379

    
380
        List<T> result = criteria.list();
381
        defaultBeanInitializer.initializeAll(result, propertyPaths);
382
        return result;
383
    }
384

    
385
    /**
386
     * @param uuids
387
     * @param pageSize
388
     * @param pageNumber
389
     * @param orderHints
390
     * @param propertyName
391
     * @return
392
     */
393
    private Criteria prepareList(Collection<?> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, String propertyName) {
394
        Criteria criteria = getSession().createCriteria(type);
395
        criteria.add(Restrictions.in(propertyName, uuids));
396

    
397
        if(pageSize != null) {
398
            criteria.setMaxResults(pageSize);
399
            if(pageNumber != null) {
400
                criteria.setFirstResult(pageNumber * pageSize);
401
            } else {
402
                criteria.setFirstResult(0);
403
            }
404
        }
405

    
406
        if(orderHints == null) {
407
            orderHints = OrderHint.defaultOrderHintsFor(type);
408
        }
409
        addOrder(criteria, orderHints);
410
        return criteria;
411
    }
412

    
413

    
414
    protected List<T> findByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
415
        Criteria criteria = null;
416

    
417
        if(clazz == null) {
418
            criteria = getSession().createCriteria(type);
419
        } else {
420
            criteria = getSession().createCriteria(clazz);
421
        }
422

    
423
        if (queryString != null) {
424
            if(matchmode == null) {
425
                criteria.add(Restrictions.ilike(param, queryString));
426
            } else if(matchmode == MatchMode.BEGINNING) {
427
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
428
            } else if(matchmode == MatchMode.END) {
429
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
430
            } else if(matchmode == MatchMode.EXACT) {
431
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
432
            } else {
433
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
434
            }
435
        }
436

    
437
        addCriteria(criteria, criterion);
438

    
439
        if(pageSize != null) {
440
            criteria.setMaxResults(pageSize);
441
            if(pageNumber != null) {
442
                criteria.setFirstResult(pageNumber * pageSize);
443
            } else {
444
                criteria.setFirstResult(0);
445
            }
446
        }
447

    
448
        addOrder(criteria, orderHints);
449

    
450
        List<T> result = criteria.list();
451
        defaultBeanInitializer.initializeAll(result, propertyPaths);
452
        return result;
453
    }
454

    
455
    @Override
456
    public T load(UUID uuid) {
457
        T bean = findByUuid(uuid);
458
        if(bean == null){
459
            return null;
460
        }
461
        defaultBeanInitializer.load(bean);
462

    
463
        return bean;
464
    }
465

    
466
    @Override
467
    public T load(int id, List<String> propertyPaths){
468
        T bean = findById(id);
469
        if(bean == null){
470
            return bean;
471
        }
472
        defaultBeanInitializer.initialize(bean, propertyPaths);
473

    
474
        return bean;
475
    }
476

    
477
    @Override
478
    public T load(UUID uuid, List<String> propertyPaths){
479
        T bean = findByUuid(uuid);
480
        if(bean == null){
481
            return bean;
482
        }
483
        defaultBeanInitializer.initialize(bean, propertyPaths);
484

    
485
        return bean;
486
    }
487

    
488
    @Override
489
    public Boolean exists(UUID uuid) {
490
        if (findByUuid(uuid)==null){
491
            return false;
492
        }
493
        return true;
494
    }
495

    
496
    @Override
497
    public int count() {
498
        return count(type);
499
    }
500

    
501
    @Override
502
    public int count(Class<? extends T> clazz) {
503
        Session session = getSession();
504
        Criteria criteria = null;
505
        if(clazz == null) {
506
            criteria = session.createCriteria(type);
507
        } else {
508
            criteria = session.createCriteria(clazz);
509
        }
510
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
511

    
512
        //since hibernate 4 (or so) uniqueResult returns Long, not Integer, therefore needs
513
        //to be casted. Think about returning long rather then int!
514
        return ((Number) criteria.uniqueResult()).intValue();
515
    }
516

    
517
    @Override
518
    public List<T> list(Integer limit, Integer start) {
519
        return list(limit, start, null);
520
    }
521

    
522
    @Override
523
    public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, List<String> propertyPaths) {
524

    
525
        Criteria criteria = null;
526
        if(clazz == null){
527
            criteria = getSession().createCriteria(type);
528
        } else {
529
            criteria = getSession().createCriteria(clazz);
530
        }
531

    
532
        addGroups(criteria,groups);
533

    
534
        if(limit != null) {
535
            criteria.setFirstResult(start);
536
            criteria.setMaxResults(limit);
537
        }
538

    
539
        List<Object[]> result = criteria.list();
540

    
541
        if(propertyPaths != null && !propertyPaths.isEmpty()) {
542
          for(Object[] objects : result) {
543
            defaultBeanInitializer.initialize(objects[0], propertyPaths);
544
          }
545
        }
546

    
547
        return result;
548
    }
549

    
550
    protected void countGroups(DetachedCriteria criteria,List<Grouping> groups) {
551
        if(groups != null){
552

    
553

    
554
            Map<String,String> aliases = new HashMap<String,String>();
555

    
556
            for(Grouping grouping : groups) {
557
                if(grouping.getAssociatedObj() != null) {
558
                    String alias = null;
559
                    if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
560
                        alias = grouping.getAssociatedObjectAlias();
561
                        aliases.put(grouping.getAssociatedObj(), alias);
562
                        criteria.createAlias(grouping.getAssociatedObj(),alias);
563
                    }
564
                }
565
            }
566

    
567
            ProjectionList projectionList = Projections.projectionList();
568

    
569
            for(Grouping grouping : groups) {
570
                grouping.addProjection(projectionList);
571
            }
572
            criteria.setProjection(projectionList);
573
        }
574
    }
575

    
576
    protected void addGroups(Criteria criteria,List<Grouping> groups) {
577
        if(groups != null){
578

    
579

    
580
            Map<String,String> aliases = new HashMap<String,String>();
581

    
582
            for(Grouping grouping : groups) {
583
                if(grouping.getAssociatedObj() != null) {
584
                    String alias = null;
585
                    if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
586
                        alias = grouping.getAssociatedObjectAlias();
587
                        aliases.put(grouping.getAssociatedObj(), alias);
588
                        criteria.createAlias(grouping.getAssociatedObj(),alias);
589
                    }
590
                }
591
            }
592

    
593
            ProjectionList projectionList = Projections.projectionList();
594

    
595
            for(Grouping grouping : groups) {
596
                grouping.addProjection(projectionList);
597
            }
598
            criteria.setProjection(projectionList);
599

    
600
            for(Grouping grouping : groups) {
601
                grouping.addOrder(criteria);
602

    
603
            }
604
        }
605
    }
606

    
607
    protected void addCriteria(Criteria criteria, List<Criterion> criterion) {
608
        if(criterion != null) {
609
            for(Criterion c : criterion) {
610
                criteria.add(c);
611
            }
612
        }
613

    
614
    }
615

    
616
    protected void addOrder(FullTextQuery fullTextQuery, List<OrderHint> orderHints) {
617
        //FIXME preliminary hardcoded type:
618
    	int type = SortField.STRING;
619

    
620
    	if(orderHints != null && !orderHints.isEmpty()) {
621
            org.apache.lucene.search.Sort sort = new Sort();
622
            SortField[] sortFields = new SortField[orderHints.size()];
623
            for(int i = 0; i < orderHints.size(); i++) {
624
                OrderHint orderHint = orderHints.get(i);
625
                switch(orderHint.getSortOrder()) {
626
                case ASCENDING:
627
                    sortFields[i] = new SortField(orderHint.getPropertyName(), type, true);
628
                    break;
629
                case DESCENDING:
630
                default:
631
                    sortFields[i] = new SortField(orderHint.getPropertyName(), type, false);
632

    
633
                }
634
            }
635
            sort.setSort(sortFields);
636
            fullTextQuery.setSort(sort);
637

    
638
        }
639
    }
640

    
641
    @Override
642
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {
643
        return list(limit,start,orderHints,null);
644
    }
645

    
646
    @Override
647
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
648
        Criteria criteria = getSession().createCriteria(type);
649
        if(limit != null) {
650
            criteria.setFirstResult(start);
651
            criteria.setMaxResults(limit);
652
        }
653

    
654
        addOrder(criteria,orderHints);
655
        List<T> results = criteria.list();
656

    
657
        defaultBeanInitializer.initializeAll(results, propertyPaths);
658
        return results;
659
    }
660

    
661
    @Override
662
    public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
663
        Criteria criteria = null;
664
        if(clazz == null) {
665
            criteria = getSession().createCriteria(type);
666
        } else {
667
            criteria = getSession().createCriteria(clazz);
668
        }
669

    
670
        if(limit != null) {
671
            if(start != null) {
672
                criteria.setFirstResult(start);
673
            } else {
674
                criteria.setFirstResult(0);
675
            }
676
            criteria.setMaxResults(limit);
677
        }
678

    
679
        addOrder(criteria,orderHints);
680

    
681
        List<S> results = criteria.list();
682
        defaultBeanInitializer.initializeAll(results, propertyPaths);
683
        return results;
684
    }
685

    
686
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints) {
687
        return list(type,limit,start,orderHints,null);
688
    }
689

    
690
    @Override
691
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start) {
692
        return list(type,limit,start,null,null);
693
    }
694

    
695
    @Override
696
    public List<T> rows(String tableName, int limit, int start) {
697
        Query query = getSession().createQuery("from " + tableName + " order by uuid");
698
        query.setFirstResult(start);
699
        query.setMaxResults(limit);
700
        List<T> result = query.list();
701
        return result;
702
    }
703

    
704
    @Override
705
    public Class<T> getType() {
706
        return type;
707
    }
708

    
709
    protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){
710
        if(pageSize != null) {
711
            query.setMaxResults(pageSize);
712
            if(pageNumber != null) {
713
                query.setFirstResult(pageNumber * pageSize);
714
            } else {
715
                query.setFirstResult(0);
716
            }
717
        }
718
    }
719

    
720
    protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageNumber){
721
        if(pageSize != null) {
722
            query.setMaxResults(pageSize);
723
            if(pageNumber != null) {
724
                query.setFirstResult(pageNumber * pageSize);
725
            } else {
726
                query.setFirstResult(0);
727
            }
728
        }
729
    }
730

    
731
    @Override
732
    public int count(T example, Set<String> includeProperties) {
733
        Criteria criteria = getSession().createCriteria(example.getClass());
734
        addExample(criteria,example,includeProperties);
735

    
736
        criteria.setProjection(Projections.rowCount());
737
        return ((Number)criteria.uniqueResult()).intValue();
738
    }
739

    
740
    protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {
741
        if(includeProperties != null && !includeProperties.isEmpty()) {
742
            criteria.add(Example.create(example).setPropertySelector(new PropertySelectorImpl(includeProperties)));
743
            ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(example.getClass());
744
            for(String property : includeProperties) {
745
                Type type  = classMetadata.getPropertyType(property);
746
                if(type.isEntityType()) {
747
                    try {
748
                        Field field = ReflectionUtils.findField(example.getClass(), property);
749
                        field.setAccessible(true);
750
                        Object value =  field.get(example);
751
                        if(value != null) {
752
                            criteria.add(Restrictions.eq(property,value));
753
                        } else {
754
                            criteria.add(Restrictions.isNull(property));
755
                        }
756
                    } catch (SecurityException se) {
757
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, se);
758
                    } catch (HibernateException he) {
759
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);
760
                    } catch (IllegalArgumentException iae) {
761
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);
762
                    } catch (IllegalAccessException ie) {
763
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);
764
                    }
765

    
766
                }
767
            }
768
        } else {
769
            criteria.add(Example.create(example));
770
        }
771
    }
772

    
773

    
774
    protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {
775
        Criteria criteria = null;
776

    
777
        if(clazz == null) {
778
            criteria = getSession().createCriteria(type);
779
        } else {
780
            criteria = getSession().createCriteria(clazz);
781
        }
782

    
783
        if (queryString != null) {
784
            if(matchmode == null) {
785
                criteria.add(Restrictions.ilike(param, queryString));
786
            } else if(matchmode == MatchMode.BEGINNING) {
787
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
788
            } else if(matchmode == MatchMode.END) {
789
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
790
            } else if(matchmode == MatchMode.EXACT) {
791
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
792
            } else {
793
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
794
            }
795
        }
796

    
797
        addCriteria(criteria, criterion);
798

    
799
        criteria.setProjection(Projections.rowCount());
800

    
801
        List<T> result = criteria.list();
802
        return ((Number)criteria.uniqueResult()).intValue();
803
    }
804

    
805

    
806
    @Override
807
    public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
808
        Criteria criteria = getSession().createCriteria(example.getClass());
809
        addExample(criteria,example,includeProperties);
810

    
811
        if(limit != null) {
812
            if(start != null) {
813
                criteria.setFirstResult(start);
814
            } else {
815
                criteria.setFirstResult(0);
816
            }
817
            criteria.setMaxResults(limit);
818
        }
819

    
820
        addOrder(criteria,orderHints);
821

    
822
        List<T> results = criteria.list();
823
        defaultBeanInitializer.initializeAll(results, propertyPaths);
824
        return results;
825
    }
826

    
827
    private class PropertySelectorImpl implements PropertySelector {
828

    
829
        private final Set<String> includeProperties;
830
        /**
831
         *
832
         */
833
        private static final long serialVersionUID = -3175311800911570546L;
834

    
835
        public PropertySelectorImpl(Set<String> includeProperties) {
836
            this.includeProperties = includeProperties;
837
        }
838

    
839
        @Override
840
        public boolean include(Object propertyValue, String propertyName,	Type type) {
841
            if(includeProperties.contains(propertyName)) {
842
                return true;
843
            } else {
844
                return false;
845
            }
846
        }
847

    
848
    }
849
}
(3-3/22)