Project

General

Profile

Download (30.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.persistence.dao.hibernate.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.FlushMode;
28
import org.hibernate.HibernateException;
29
import org.hibernate.LockOptions;
30
import org.hibernate.NonUniqueObjectException;
31
import org.hibernate.Query;
32
import org.hibernate.Session;
33
import org.hibernate.criterion.Criterion;
34
import org.hibernate.criterion.DetachedCriteria;
35
import org.hibernate.criterion.Example;
36
import org.hibernate.criterion.Example.PropertySelector;
37
import org.hibernate.criterion.Order;
38
import org.hibernate.criterion.ProjectionList;
39
import org.hibernate.criterion.Projections;
40
import org.hibernate.criterion.Restrictions;
41
import org.hibernate.envers.query.AuditQuery;
42
import org.hibernate.metadata.ClassMetadata;
43
import org.hibernate.search.FullTextQuery;
44
import org.hibernate.type.Type;
45
import org.springframework.beans.factory.annotation.Autowired;
46
import org.springframework.dao.DataAccessException;
47
import org.springframework.dao.InvalidDataAccessApiUsageException;
48
import org.springframework.stereotype.Repository;
49
import org.springframework.util.ReflectionUtils;
50

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

    
61

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

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

    
72
    protected Class<T> type;
73

    
74
    protected Version version = Configuration.luceneVersion;
75

    
76
    @Autowired
77
//	@Qualifier("defaultBeanInitializer")
78
    protected IBeanInitializer defaultBeanInitializer;
79

    
80
    public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer) {
81
        this.defaultBeanInitializer = defaultBeanInitializer;
82
    }
83

    
84
    @Autowired
85
    private ReferringObjectMetadataFactory referringObjectMetadataFactory;
86

    
87

    
88
    public CdmEntityDaoBase(Class<T> type){
89
        this.type = type;
90
        logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");
91
    }
92

    
93
    @Override
94
    public void lock(T t, LockOptions lockOptions) {
95
        getSession().buildLockRequest(lockOptions).lock(t);
96
    }
97

    
98
    @Override
99
    public void refresh(T t, LockOptions lockOptions, List<String> propertyPaths) {
100
        getSession().refresh(t, lockOptions);
101
        defaultBeanInitializer.initialize(t, propertyPaths);
102
    }
103

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

    
110
    //TODO: Replace saveCdmObj() by saveCdmObject_
111
    private UUID saveCdmObject_(T cdmObj){
112
        getSession().saveOrUpdate(cdmObj);
113
        return cdmObj.getUuid();
114
    }
115

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

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

    
147
        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
148
        return resultMap;
149
    }
150

    
151
    private UUID saveOrUpdateCdmObject(T cdmObj){
152
        getSession().saveOrUpdate(cdmObj);
153
        return cdmObj.getUuid();
154
    }
155

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

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

    
185
        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
186
        return resultMap;
187
    }
188

    
189

    
190

    
191

    
192
    @Override
193
    public T replace(T x, T y) {
194
        if(x.equals(y)) {
195
            return y;
196
        }
197

    
198
        Class<?> commonClass = x.getClass();
199
        if(y != null) {
200
            while(!commonClass.isAssignableFrom(y.getClass())) {
201
                if(commonClass.equals(type)) {
202
                    throw new RuntimeException();
203
                }
204
                commonClass = commonClass.getSuperclass();
205
            }
206
        }
207

    
208
        getSession().merge(x);
209

    
210
        Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());
211

    
212
        for(ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {
213

    
214
          List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x, getSession());
215

    
216
          for(CdmBase referringObject : referringObjects) {
217
            try {
218
                referringObjectMetadata.replace(referringObject,x,y);
219
                getSession().update(referringObject);
220

    
221
            } catch (IllegalArgumentException e) {
222
                throw new RuntimeException(e.getMessage(),e);
223
            } catch (IllegalAccessException e) {
224
                throw new RuntimeException(e.getMessage(),e);
225
            }
226
          }
227
        }
228
        return y;
229
    }
230

    
231
    @Override
232
    public Session getSession() throws DataAccessException {
233
        return super.getSession();
234
    }
235

    
236
    @Override
237
    public void clear() throws DataAccessException {
238
        Session session = getSession();
239
        session.clear();
240
        if (logger.isDebugEnabled()){logger.debug("dao clear end");}
241
    }
242

    
243
    @Override
244
    public T merge(T transientObject, boolean returnTransientEntity) throws DataAccessException {
245
        T persistentObject = merge(transientObject);
246
        if(returnTransientEntity) {
247
            if(transientObject != null && persistentObject != null) {
248
                transientObject.setId(persistentObject.getId());
249
            }
250
            return transientObject;
251
        } else {
252
            return persistentObject;
253
        }
254
    }
255

    
256
    @Override
257
    public T merge(T transientObject) throws DataAccessException {
258
        if(transientObject == null) {
259
            return null;
260
        }
261
        Session session = getSession();
262
        @SuppressWarnings("unchecked")
263
		T persistentObject = (T)session.merge(transientObject);
264
        if (logger.isDebugEnabled()){logger.debug("dao merge end");}
265
        return persistentObject;
266
    }
267

    
268
    @Override
269
    public UUID saveOrUpdate(T transientObject) throws DataAccessException  {
270
        if (transientObject == null){
271
        	logger.warn("Object to save should not be null. NOP");
272
        	return null;
273
        }
274
    	try {
275
            if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate start...");}
276
            if (logger.isDebugEnabled()){logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:" + transientObject.getId() + ", UUID: " + transientObject.getUuid()) ;}
277
            Session session = getSession();
278
            session.saveOrUpdate(transientObject);
279
            if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}
280
            return transientObject.getUuid();
281
        } catch (NonUniqueObjectException e) {
282
            logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj)");
283
            logger.error(e.getIdentifier());
284
            logger.error(e.getEntityName());
285
            logger.error(e.getMessage());
286

    
287
            e.printStackTrace();
288
            throw e;
289
        } catch (HibernateException e) {
290

    
291
            e.printStackTrace();
292
            throw e;
293
        }
294
    }
295

    
296
    @Override
297
    public T save(T newInstance) throws DataAccessException {
298
        if (newInstance == null){
299
        	logger.warn("Object to save should not be null. NOP");
300
        	return null;
301
        }
302
    	getSession().save(newInstance);
303
        return newInstance;
304
    }
305

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

    
316
    @Override
317
    public UUID refresh(T persistentObject) throws DataAccessException {
318
        getSession().refresh(persistentObject);
319
        return persistentObject.getUuid();
320
    }
321

    
322
    @Override
323
    public UUID delete(T persistentObject) throws DataAccessException {
324
        if (persistentObject == null){
325
            logger.warn(type.getName() + " was 'null'");
326
            return null;
327
        }
328

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

    
339
    @SuppressWarnings("unchecked")
340
	@Override
341
    public T findById(int id) throws DataAccessException {
342
        return (T) getSession().get(type, id);
343
    }
344

    
345

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

    
364
    @Override
365
    public T findByUuidWithoutFlush(UUID uuid) throws DataAccessException{
366
    	Session session = getSession();
367
    	FlushMode currentFlushMode = session.getFlushMode();
368
    	try {
369
    		// set flush mode to manual so that the session does not flush
370
    		// when before performing the query
371
    		session.setFlushMode(FlushMode.MANUAL);
372
    		Criteria crit = session.createCriteria(type);
373
    		crit.add(Restrictions.eq("uuid", uuid));
374
    		crit.addOrder(Order.desc("created"));
375
    		@SuppressWarnings("unchecked")
376
			List<T> results = crit.list();
377
    		if (results.isEmpty()){
378
    			return null;
379
    		}else{
380
    			if(results.size() > 1){
381
    				logger.error("findByUuid() delivers more than one result for UUID: " + uuid);
382
    			}
383
    			return results.get(0);
384
    		}
385
    	} finally {
386
    		// set back the session flush mode
387
    		if(currentFlushMode != null) {
388
    			session.setFlushMode(currentFlushMode);
389
    		}
390
    	}
391
    }
392

    
393
    @Override
394
    public List<T> listByIds(Collection<Integer> ids,  Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {
395

    
396
        if (ids.isEmpty()) {
397
            return new ArrayList<T>(0);
398
        }
399

    
400
        Criteria criteria = prepareList(ids, pageSize, pageNumber, orderHints, "id");
401

    
402
        if (logger.isDebugEnabled()){logger.debug(criteria.toString());};
403

    
404
         @SuppressWarnings("unchecked")
405
		List<T> result = criteria.list();
406
         defaultBeanInitializer.initializeAll(result, propertyPaths);
407
         return result;
408
     }
409

    
410

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

    
414
        Criteria criteria = prepareList(uuids, pageSize, pageNumber, orderHints, "uuid");
415

    
416
        @SuppressWarnings("unchecked")
417
		List<T> result = criteria.list();
418
        defaultBeanInitializer.initializeAll(result, propertyPaths);
419
        return result;
420
    }
421

    
422
    /**
423
     * @param uuids
424
     * @param pageSize
425
     * @param pageNumber
426
     * @param orderHints
427
     * @param propertyName
428
     * @return
429
     */
430
    private Criteria prepareList(Collection<?> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, String propertyName) {
431
        Criteria criteria = getSession().createCriteria(type);
432
        criteria.add(Restrictions.in(propertyName, uuids));
433

    
434
        if(pageSize != null) {
435
            criteria.setMaxResults(pageSize);
436
            if(pageNumber != null) {
437
                criteria.setFirstResult(pageNumber * pageSize);
438
            } else {
439
                criteria.setFirstResult(0);
440
            }
441
        }
442

    
443
        if(orderHints == null) {
444
            orderHints = OrderHint.defaultOrderHintsFor(type);
445
        }
446
        addOrder(criteria, orderHints);
447
        return criteria;
448
    }
449

    
450

    
451
    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) {
452
        Criteria criteria = null;
453

    
454
        if(clazz == null) {
455
            criteria = getSession().createCriteria(type);
456
        } else {
457
            criteria = getSession().createCriteria(clazz);
458
        }
459

    
460
        if (queryString != null) {
461
            if(matchmode == null) {
462
                criteria.add(Restrictions.ilike(param, queryString));
463
            } else if(matchmode == MatchMode.BEGINNING) {
464
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
465
            } else if(matchmode == MatchMode.END) {
466
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
467
            } else if(matchmode == MatchMode.EXACT) {
468
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
469
            } else {
470
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
471
            }
472
        }
473

    
474
        addCriteria(criteria, criterion);
475

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

    
485
        addOrder(criteria, orderHints);
486

    
487
        @SuppressWarnings("unchecked")
488
		List<T> result = criteria.list();
489
        defaultBeanInitializer.initializeAll(result, propertyPaths);
490
        return result;
491
    }
492

    
493
    @Override
494
    public T load(UUID uuid) {
495
        T bean = findByUuid(uuid);
496
        if(bean == null){
497
            return null;
498
        }
499
        defaultBeanInitializer.load(bean);
500

    
501
        return bean;
502
    }
503

    
504
    @Override
505
    public T load(int id, List<String> propertyPaths){
506
        T bean = findById(id);
507
        if(bean == null){
508
            return bean;
509
        }
510
        defaultBeanInitializer.initialize(bean, propertyPaths);
511

    
512
        return bean;
513
    }
514

    
515
    @Override
516
    public T load(UUID uuid, List<String> propertyPaths){
517
        T bean = findByUuid(uuid);
518
        if(bean == null){
519
            return bean;
520
        }
521
        defaultBeanInitializer.initialize(bean, propertyPaths);
522

    
523
        return bean;
524
    }
525

    
526
    @Override
527
    public Boolean exists(UUID uuid) {
528
        if (findByUuid(uuid)==null){
529
            return false;
530
        }
531
        return true;
532
    }
533

    
534
    @Override
535
    public int count() {
536
        return count(type);
537
    }
538

    
539
    @Override
540
    public int count(Class<? extends T> clazz) {
541
        Session session = getSession();
542
        Criteria criteria = null;
543
        if(clazz == null) {
544
            criteria = session.createCriteria(type);
545
        } else {
546
            criteria = session.createCriteria(clazz);
547
        }
548
        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
549

    
550
        //since hibernate 4 (or so) uniqueResult returns Long, not Integer, therefore needs
551
        //to be casted. Think about returning long rather then int!
552
        return ((Number) criteria.uniqueResult()).intValue();
553
    }
554

    
555
    @Override
556
    public List<T> list(Integer limit, Integer start) {
557
        return list(limit, start, null);
558
    }
559

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

    
563
        Criteria criteria = null;
564
        if(clazz == null){
565
            criteria = getSession().createCriteria(type);
566
        } else {
567
            criteria = getSession().createCriteria(clazz);
568
        }
569

    
570
        addGroups(criteria,groups);
571

    
572
        if(limit != null) {
573
            criteria.setFirstResult(start);
574
            criteria.setMaxResults(limit);
575
        }
576

    
577
        @SuppressWarnings("unchecked")
578
		List<Object[]> result = criteria.list();
579

    
580
        if(propertyPaths != null && !propertyPaths.isEmpty()) {
581
          for(Object[] objects : result) {
582
            defaultBeanInitializer.initialize(objects[0], propertyPaths);
583
          }
584
        }
585

    
586
        return result;
587
    }
588

    
589
    protected void countGroups(DetachedCriteria criteria,List<Grouping> groups) {
590
        if(groups != null){
591

    
592

    
593
            Map<String,String> aliases = new HashMap<String,String>();
594

    
595
            for(Grouping grouping : groups) {
596
                if(grouping.getAssociatedObj() != null) {
597
                    String alias = null;
598
                    if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
599
                        alias = grouping.getAssociatedObjectAlias();
600
                        aliases.put(grouping.getAssociatedObj(), alias);
601
                        criteria.createAlias(grouping.getAssociatedObj(),alias);
602
                    }
603
                }
604
            }
605

    
606
            ProjectionList projectionList = Projections.projectionList();
607

    
608
            for(Grouping grouping : groups) {
609
                grouping.addProjection(projectionList);
610
            }
611
            criteria.setProjection(projectionList);
612
        }
613
    }
614

    
615
    protected void addGroups(Criteria criteria,List<Grouping> groups) {
616
        if(groups != null){
617

    
618

    
619
            Map<String,String> aliases = new HashMap<String,String>();
620

    
621
            for(Grouping grouping : groups) {
622
                if(grouping.getAssociatedObj() != null) {
623
                    String alias = null;
624
                    if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
625
                        alias = grouping.getAssociatedObjectAlias();
626
                        aliases.put(grouping.getAssociatedObj(), alias);
627
                        criteria.createAlias(grouping.getAssociatedObj(),alias);
628
                    }
629
                }
630
            }
631

    
632
            ProjectionList projectionList = Projections.projectionList();
633

    
634
            for(Grouping grouping : groups) {
635
                grouping.addProjection(projectionList);
636
            }
637
            criteria.setProjection(projectionList);
638

    
639
            for(Grouping grouping : groups) {
640
                grouping.addOrder(criteria);
641

    
642
            }
643
        }
644
    }
645

    
646
    protected void addCriteria(Criteria criteria, List<Criterion> criterion) {
647
        if(criterion != null) {
648
            for(Criterion c : criterion) {
649
                criteria.add(c);
650
            }
651
        }
652

    
653
    }
654

    
655
    protected void addOrder(FullTextQuery fullTextQuery, List<OrderHint> orderHints) {
656
        //FIXME preliminary hardcoded type:
657
    	int type = SortField.STRING;
658

    
659
    	if(orderHints != null && !orderHints.isEmpty()) {
660
            org.apache.lucene.search.Sort sort = new Sort();
661
            SortField[] sortFields = new SortField[orderHints.size()];
662
            for(int i = 0; i < orderHints.size(); i++) {
663
                OrderHint orderHint = orderHints.get(i);
664
                switch(orderHint.getSortOrder()) {
665
                case ASCENDING:
666
                    sortFields[i] = new SortField(orderHint.getPropertyName(), type, true);
667
                    break;
668
                case DESCENDING:
669
                default:
670
                    sortFields[i] = new SortField(orderHint.getPropertyName(), type, false);
671

    
672
                }
673
            }
674
            sort.setSort(sortFields);
675
            fullTextQuery.setSort(sort);
676

    
677
        }
678
    }
679

    
680
    @Override
681
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {
682
        return list(limit,start,orderHints,null);
683
    }
684

    
685
    @Override
686
    public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
687
        Criteria criteria = getSession().createCriteria(type);
688
        if(limit != null) {
689
            criteria.setFirstResult(start);
690
            criteria.setMaxResults(limit);
691
        }
692

    
693
        addOrder(criteria,orderHints);
694
        @SuppressWarnings("unchecked")
695
		List<T> results = criteria.list();
696

    
697
        defaultBeanInitializer.initializeAll(results, propertyPaths);
698
        return results;
699
    }
700

    
701
    @Override
702
    public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
703
        Criteria criteria = null;
704
        if(clazz == null) {
705
            criteria = getSession().createCriteria(type);
706
        } else {
707
            criteria = getSession().createCriteria(clazz);
708
        }
709

    
710
        if(limit != null) {
711
            if(start != null) {
712
                criteria.setFirstResult(start);
713
            } else {
714
                criteria.setFirstResult(0);
715
            }
716
            criteria.setMaxResults(limit);
717
        }
718

    
719
        addOrder(criteria,orderHints);
720

    
721
        @SuppressWarnings("unchecked")
722
		List<S> results = criteria.list();
723
        defaultBeanInitializer.initializeAll(results, propertyPaths);
724
        return results;
725
    }
726

    
727
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints) {
728
        return list(type,limit,start,orderHints,null);
729
    }
730

    
731
    @Override
732
    public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start) {
733
        return list(type,limit,start,null,null);
734
    }
735

    
736
    @Override
737
    public List<T> rows(String tableName, int limit, int start) {
738
        Query query = getSession().createQuery("from " + tableName + " order by uuid");
739
        query.setFirstResult(start);
740
        query.setMaxResults(limit);
741
        @SuppressWarnings("unchecked")
742
		List<T> result = query.list();
743
        return result;
744
    }
745

    
746
    @Override
747
    public Class<T> getType() {
748
        return type;
749
    }
750

    
751
    protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){
752
        if(pageSize != null) {
753
            query.setMaxResults(pageSize);
754
            if(pageNumber != null) {
755
                query.setFirstResult(pageNumber * pageSize);
756
            } else {
757
                query.setFirstResult(0);
758
            }
759
        }
760
    }
761

    
762
    protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageNumber){
763
        if(pageSize != null) {
764
            query.setMaxResults(pageSize);
765
            if(pageNumber != null) {
766
                query.setFirstResult(pageNumber * pageSize);
767
            } else {
768
                query.setFirstResult(0);
769
            }
770
        }
771
    }
772

    
773
    @Override
774
    public int count(T example, Set<String> includeProperties) {
775
        Criteria criteria = getSession().createCriteria(example.getClass());
776
        addExample(criteria,example,includeProperties);
777

    
778
        criteria.setProjection(Projections.rowCount());
779
        return ((Number)criteria.uniqueResult()).intValue();
780
    }
781

    
782
    protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {
783
        if(includeProperties != null && !includeProperties.isEmpty()) {
784
            criteria.add(Example.create(example).setPropertySelector(new PropertySelectorImpl(includeProperties)));
785
            ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(example.getClass());
786
            for(String property : includeProperties) {
787
                Type type  = classMetadata.getPropertyType(property);
788
                if(type.isEntityType()) {
789
                    try {
790
                        Field field = ReflectionUtils.findField(example.getClass(), property);
791
                        field.setAccessible(true);
792
                        Object value =  field.get(example);
793
                        if(value != null) {
794
                            criteria.add(Restrictions.eq(property,value));
795
                        } else {
796
                            criteria.add(Restrictions.isNull(property));
797
                        }
798
                    } catch (SecurityException se) {
799
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, se);
800
                    } catch (HibernateException he) {
801
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);
802
                    } catch (IllegalArgumentException iae) {
803
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);
804
                    } catch (IllegalAccessException ie) {
805
                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);
806
                    }
807

    
808
                }
809
            }
810
        } else {
811
            criteria.add(Example.create(example));
812
        }
813
    }
814

    
815

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

    
819
        if(clazz == null) {
820
            criteria = getSession().createCriteria(type);
821
        } else {
822
            criteria = getSession().createCriteria(clazz);
823
        }
824

    
825
        if (queryString != null) {
826
            if(matchmode == null) {
827
                criteria.add(Restrictions.ilike(param, queryString));
828
            } else if(matchmode == MatchMode.BEGINNING) {
829
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
830
            } else if(matchmode == MatchMode.END) {
831
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
832
            } else if(matchmode == MatchMode.EXACT) {
833
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
834
            } else {
835
                criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
836
            }
837
        }
838

    
839
        addCriteria(criteria, criterion);
840

    
841
        criteria.setProjection(Projections.rowCount());
842

    
843
//        List<T> result = criteria.list();
844
        return ((Number)criteria.uniqueResult()).intValue();
845
    }
846

    
847

    
848
    @Override
849
    public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
850
        Criteria criteria = getSession().createCriteria(example.getClass());
851
        addExample(criteria,example,includeProperties);
852

    
853
        if(limit != null) {
854
            if(start != null) {
855
                criteria.setFirstResult(start);
856
            } else {
857
                criteria.setFirstResult(0);
858
            }
859
            criteria.setMaxResults(limit);
860
        }
861

    
862
        addOrder(criteria,orderHints);
863

    
864
        @SuppressWarnings("unchecked")
865
		List<T> results = criteria.list();
866
        defaultBeanInitializer.initializeAll(results, propertyPaths);
867
        return results;
868
    }
869

    
870
    private class PropertySelectorImpl implements PropertySelector {
871

    
872
        private final Set<String> includeProperties;
873
        /**
874
         *
875
         */
876
        private static final long serialVersionUID = -3175311800911570546L;
877

    
878
        public PropertySelectorImpl(Set<String> includeProperties) {
879
            this.includeProperties = includeProperties;
880
        }
881

    
882
        @Override
883
        public boolean include(Object propertyValue, String propertyName,	Type type) {
884
            if(includeProperties.contains(propertyName)) {
885
                return true;
886
            } else {
887
                return false;
888
            }
889
        }
890

    
891
    }
892
}
(3-3/23)