Project

General

Profile

Download (24.5 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.Collection;
14
import java.util.HashMap;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.apache.log4j.Logger;
22
import org.apache.lucene.search.Sort;
23
import org.apache.lucene.search.SortField;
24
import org.hibernate.Criteria;
25
import org.hibernate.HibernateException;
26
import org.hibernate.LockMode;
27
import org.hibernate.NonUniqueObjectException;
28
import org.hibernate.Query;
29
import org.hibernate.Session;
30
import org.hibernate.criterion.Criterion;
31
import org.hibernate.criterion.DetachedCriteria;
32
import org.hibernate.criterion.Example;
33
import org.hibernate.criterion.Example.PropertySelector;
34
import org.hibernate.criterion.Order;
35
import org.hibernate.criterion.ProjectionList;
36
import org.hibernate.criterion.Projections;
37
import org.hibernate.criterion.Restrictions;
38
import org.hibernate.envers.query.AuditQuery;
39
import org.hibernate.metadata.ClassMetadata;
40
import org.hibernate.search.FullTextQuery;
41
import org.hibernate.type.Type;
42
import org.joda.time.DateTime;
43
import org.springframework.beans.factory.annotation.Autowired;
44
import org.springframework.dao.DataAccessException;
45
import org.springframework.dao.InvalidDataAccessApiUsageException;
46
import org.springframework.security.core.Authentication;
47
import org.springframework.security.core.context.SecurityContextHolder;
48
import org.springframework.stereotype.Repository;
49
import org.springframework.util.ReflectionUtils;
50

    
51
import eu.etaxonomy.cdm.model.common.CdmBase;
52
import eu.etaxonomy.cdm.model.common.User;
53
import eu.etaxonomy.cdm.model.common.VersionableEntity;
54
import eu.etaxonomy.cdm.persistence.dao.BeanInitializer;
55
import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
56
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadata;
57
import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadataFactory;
58
import eu.etaxonomy.cdm.persistence.query.Grouping;
59
import eu.etaxonomy.cdm.persistence.query.MatchMode;
60
import eu.etaxonomy.cdm.persistence.query.OrderHint;
61

    
62

    
63
/**
64
 * @author a.mueller
65
 * FIXME CdmEntityDaoBase is abstract, can it be annotated with @Repository?
66
 */
67
@Repository
68
public abstract class CdmEntityDaoBase<T extends CdmBase> extends DaoBase implements ICdmEntityDao<T> {
69
	private static final Logger logger = Logger.getLogger(CdmEntityDaoBase.class);
70
	
71
	protected int flushAfterNo = 1000; //large numbers may cause synchronisation errors when commiting the session !!
72
	protected Class<T> type;
73
	
74
	@Autowired
75
//	@Qualifier("defaultBeanInitializer")
76
	protected BeanInitializer defaultBeanInitializer;
77
	
78
	public void setDefaultBeanInitializer(BeanInitializer defaultBeanInitializer) {
79
		this.defaultBeanInitializer = defaultBeanInitializer;
80
	}
81

    
82
	@Autowired
83
	private ReferringObjectMetadataFactory referringObjectMetadataFactory;
84
	
85
	
86
	public CdmEntityDaoBase(Class<T> type){
87
		this.type = type;
88
		logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");
89
	}
90
	
91
	public void lock(T t, LockMode lockMode) {
92
		getSession().lock(t, lockMode);
93
	}
94
	
95
	public void refresh(T t, LockMode lockMode, List<String> propertyPaths) {
96
		getSession().refresh(t, lockMode);
97
		defaultBeanInitializer.initialize(t, propertyPaths);
98
	}
99
	
100
	//TODO this method should be moved to a concrete class (not typed)
101
	public UUID saveCdmObj(CdmBase cdmObj) throws DataAccessException  {
102
		getSession().saveOrUpdate(cdmObj);
103
		return cdmObj.getUuid();
104
	}
105
	
106
    //TODO: Replace saveCdmObj() by saveCdmObject_
107
	private UUID saveCdmObject_(T cdmObj){
108
		getSession().saveOrUpdate(cdmObj);
109
		return cdmObj.getUuid();
110
	}
111
	
112
    //TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of ServiceBase.saveCdmObjectAll()?
113
	//TODO: why does this use saveCdmObject_ which actually savesOrUpdateds data ?
114
	public Map<UUID, T> saveAll(Collection<T> cdmObjCollection){
115
		int types = cdmObjCollection.getClass().getTypeParameters().length;
116
		if (types > 0){
117
			if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}
118
		}
119

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

    
142
		if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
143
		return resultMap;
144
	}
145
	
146
    private UUID saveOrUpdateCdmObject(T cdmObj){
147
		getSession().saveOrUpdate(cdmObj);
148
		return cdmObj.getUuid();
149
	}
150
    
151
	public Map<UUID, T> saveOrUpdateAll(Collection<T> cdmObjCollection){
152
		int types = cdmObjCollection.getClass().getTypeParameters().length;
153
		if (types > 0){
154
			if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}
155
		}
156

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

    
179
		if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
180
		return resultMap;
181
	}
182
	
183
	
184
	
185
	
186
	public T replace(T x, T y) {
187
		if(x.equals(y)) {
188
			return y;
189
		}
190
		
191
		Class commonClass = x.getClass();
192
		if(y != null) {
193
            while(!commonClass.isAssignableFrom(y.getClass())) {
194
        	    if(commonClass.equals(type)) {
195
        		    throw new RuntimeException();
196
        	    }
197
        	    commonClass = commonClass.getSuperclass();
198
            }
199
		}
200

    
201
		getSession().merge(x);
202
		
203
        Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());
204
        
205
        for(ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {
206
          
207
          List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x,getSession());
208
         
209
          for(CdmBase referringObject : referringObjects) {
210
            try {
211
				referringObjectMetadata.replace(referringObject,x,y);
212
				getSession().update(referringObject);
213
              
214
			} catch (IllegalArgumentException e) {
215
				throw new RuntimeException(e.getMessage(),e);
216
			} catch (IllegalAccessException e) {
217
				throw new RuntimeException(e.getMessage(),e);
218
			}
219
          }
220
        }
221
        return y;
222
    }
223

    
224
	public Session getSession() throws DataAccessException {
225
		return super.getSession();
226
	}
227

    
228
	public void clear() throws DataAccessException {
229
		Session session = getSession();
230
		session.clear();
231
		if (logger.isDebugEnabled()){logger.debug("dao clear end");}
232
	}
233

    
234
	public T merge(T transientObject) throws DataAccessException {
235
		Session session = getSession();
236
		T persistentObject = (T)session.merge(transientObject);
237
		if (logger.isDebugEnabled()){logger.debug("dao merge end");}
238
		return persistentObject;
239
	}
240
	
241
	public UUID saveOrUpdate(T transientObject) throws DataAccessException  {
242
		try {
243
			if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate start...");}
244
			if (logger.isDebugEnabled()){logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:" + transientObject.getId() + ", UUID: " + transientObject.getUuid()) ;}
245
			Session session = getSession();
246
			if(transientObject.getId() != 0 && VersionableEntity.class.isAssignableFrom(transientObject.getClass())) {
247
				VersionableEntity versionableEntity = (VersionableEntity)transientObject;
248
				versionableEntity.setUpdated(new DateTime());
249
				Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
250
				if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
251
				  User user = (User)authentication.getPrincipal();
252
				  versionableEntity.setUpdatedBy(user);
253
				} 
254
			}
255
			session.saveOrUpdate(transientObject);
256
			if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}
257
			return transientObject.getUuid();
258
		} catch (NonUniqueObjectException e) {
259
			logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj)");
260
			logger.error(e.getIdentifier());
261
			logger.error(e.getEntityName());
262
			logger.error(e.getMessage());
263
			
264
			e.printStackTrace();
265
			throw e;
266
		} catch (HibernateException e) {
267
			
268
			e.printStackTrace();
269
			throw e;
270
		}
271
	}
272

    
273
	public UUID save(T newInstance) throws DataAccessException {
274
		getSession().save(newInstance);
275
		return newInstance.getUuid();
276
	}
277
	
278
	public UUID update(T transientObject) throws DataAccessException {
279
		getSession().update(transientObject);
280
		return transientObject.getUuid();
281
	}
282
	
283
	public UUID refresh(T persistentObject) throws DataAccessException {
284
		getSession().refresh(persistentObject);
285
		return persistentObject.getUuid();
286
	}
287
	
288
	public UUID delete(T persistentObject) throws DataAccessException {
289
		if (persistentObject == null){
290
			logger.warn(type.getName() + " was 'null'");
291
			return null;
292
		}
293
		
294
		// Merge the object in if it is detached
295
		//
296
		// I think this is preferable to catching lazy initialization errors 
297
		// as that solution only swallows and hides the exception, but doesn't 
298
		// actually solve it.
299
		getSession().merge(persistentObject);
300
		getSession().delete(persistentObject);
301
		return persistentObject.getUuid();
302
	}
303

    
304
	public T findById(int id) throws DataAccessException {
305
		return (T) getSession().get(type, id);
306
	}
307
	public List<T> findById(Set<Integer> idSet) throws DataAccessException {
308
		Session session = getSession();
309
		String hql = "from " + type.getSimpleName() + " type where type.id in ( :idSet )" ;
310
		Query query = session.createQuery(hql);
311
		query.setParameterList("idSet", idSet);
312
		List<T> results = query.list();
313
		return results;			
314
	}
315
	public T findByUuid(UUID uuid) throws DataAccessException{
316
		Session session = getSession();
317
		Criteria crit = session.createCriteria(type);
318
		crit.add(Restrictions.eq("uuid", uuid));
319
		crit.addOrder(Order.desc("created"));
320
		List<T> results = crit.list();
321
		if (results.isEmpty()){
322
			return null;
323
		}else{
324
			if(results.size() > 1){
325
				logger.error("findByUuid() delivers more than one result for UUID: " + uuid);
326
			}
327
			return results.get(0);			
328
		}
329
	}
330
	
331
	public List<T> findByUuid(Set<UUID> uuidSet) throws DataAccessException {
332
		Session session = getSession();
333
		String hql = "from " + type.getSimpleName() + " type where type.uuid in ( :uuidSet )" ;
334
		Query query = session.createQuery(hql);
335
		query.setParameterList("uuidSet", uuidSet);
336
		List<T> results = query.list();
337
		return results;			
338
	}
339
	
340
    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) {
341
    	Criteria criteria = null;
342

    
343
    	if(clazz == null) {
344
    		criteria = getSession().createCriteria(type);
345
    	} else {
346
    		criteria = getSession().createCriteria(clazz);
347
    	}
348

    
349
    	if (queryString != null) {
350
    		if(matchmode == null) {
351
    			criteria.add(Restrictions.ilike(param, queryString));
352
    		} else if(matchmode == MatchMode.BEGINNING) {
353
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
354
    		} else if(matchmode == MatchMode.END) {
355
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
356
    		} else if(matchmode == MatchMode.EXACT) {
357
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
358
    		} else {
359
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
360
    		}
361
    	}
362
    	
363
    	addCriteria(criteria, criterion);
364

    
365
    	if(pageSize != null) {
366
    		criteria.setMaxResults(pageSize);
367
    		if(pageNumber != null) {
368
    			criteria.setFirstResult(pageNumber * pageSize);
369
    		} else {
370
    			criteria.setFirstResult(0);
371
    		}
372
    	}
373

    
374
    	addOrder(criteria, orderHints);
375

    
376
    	List<T> result = (List<T>)criteria.list();
377
    	defaultBeanInitializer.initializeAll(result, propertyPaths);
378
    	return result;
379
    }
380
	
381
	public T load(UUID uuid) {
382
		T bean = findByUuid(uuid);
383
		if(bean == null){ 
384
			return null;
385
		}
386
		defaultBeanInitializer.load(bean);
387
		
388
		return bean;
389
	}
390
	
391

    
392
	public T load(UUID uuid, List<String> propertyPaths){
393
		T bean = findByUuid(uuid);
394
		if(bean == null){ 
395
			return bean;
396
		}
397
		defaultBeanInitializer.initialize(bean, propertyPaths);
398
		
399
		return bean;
400
	}
401
	
402
	public List<T> load(Set<UUID> uuidSet, List<String> propertyPaths) throws DataAccessException{
403
		List<T> list = findByUuid(uuidSet);
404
		defaultBeanInitializer.initializeAll(list, propertyPaths);
405
		return list;
406
	}
407
	
408
	public Boolean exists(UUID uuid) {
409
		if (findByUuid(uuid)==null){
410
			return false;
411
		}
412
		return true;
413
	}
414
	
415
	public int count() {
416
		return count(type);
417
	}
418
	
419
	public int count(Class<? extends T> clazz) {
420
		Session session = getSession();
421
		Criteria criteria = null;
422
		if(clazz == null) {
423
			criteria = session.createCriteria(type);
424
		} else {
425
		    criteria = session.createCriteria(clazz);
426
		}
427
		criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
428
		return (Integer) criteria.uniqueResult();
429
	}
430

    
431
	public List<T> list(Integer limit, Integer start) {
432
		return list(limit, start, null); 
433
	}
434
	
435
	public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, List<String> propertyPaths) {
436
		
437
		Criteria criteria = null;
438
		if(clazz == null){
439
			criteria = getSession().createCriteria(type);
440
		} else {
441
			criteria = getSession().createCriteria(clazz);
442
		}
443
		
444
		addGroups(criteria,groups);
445
		
446
		if(limit != null) {
447
			criteria.setFirstResult(start);
448
			criteria.setMaxResults(limit);
449
		}
450
		
451
		List<Object[]> result = (List<Object[]>)criteria.list();
452
		
453
		if(propertyPaths != null && !propertyPaths.isEmpty()) {
454
		  for(Object[] objects : result) {
455
			defaultBeanInitializer.initialize(objects[0], propertyPaths);
456
		  }
457
		}
458
		
459
		return result;		
460
	}
461
	
462
	protected void countGroups(DetachedCriteria criteria,List<Grouping> groups) {
463
		if(groups != null){
464

    
465

    
466
			Map<String,String> aliases = new HashMap<String,String>();
467

    
468
			for(Grouping grouping : groups) {
469
				if(grouping.getAssociatedObj() != null) {
470
					String alias = null;
471
					if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
472
						alias = grouping.getAssociatedObjectAlias();
473
						aliases.put(grouping.getAssociatedObj(), alias);
474
						criteria.createAlias(grouping.getAssociatedObj(),alias);
475
					}
476
				}
477
			}
478

    
479
			ProjectionList projectionList = Projections.projectionList();
480

    
481
			for(Grouping grouping : groups) {
482
				grouping.addProjection(projectionList);
483
			}
484
			criteria.setProjection(projectionList);
485
		}
486
	}  
487
	
488
	protected void addGroups(Criteria criteria,List<Grouping> groups) {
489
		if(groups != null){
490

    
491

    
492
			Map<String,String> aliases = new HashMap<String,String>();
493

    
494
			for(Grouping grouping : groups) {
495
				if(grouping.getAssociatedObj() != null) {
496
					String alias = null;
497
					if((alias = aliases.get(grouping.getAssociatedObj())) == null) {
498
						alias = grouping.getAssociatedObjectAlias();
499
						aliases.put(grouping.getAssociatedObj(), alias);
500
						criteria.createAlias(grouping.getAssociatedObj(),alias);
501
					}
502
				}
503
			}
504

    
505
			ProjectionList projectionList = Projections.projectionList();
506

    
507
			for(Grouping grouping : groups) {
508
				grouping.addProjection(projectionList);
509
			}
510
			criteria.setProjection(projectionList);
511
			
512
			for(Grouping grouping : groups) {
513
				grouping.addOrder(criteria);
514

    
515
			}
516
		}
517
	}  
518
	
519
	protected void addCriteria(Criteria criteria, List<Criterion> criterion) {
520
		if(criterion != null) {
521
			for(Criterion c : criterion) {
522
				criteria.add(c);
523
			}
524
		}
525
			
526
	}
527
	
528
	protected void addOrder(FullTextQuery fullTextQuery, List<OrderHint> orderHints) {
529
		if(orderHints != null && !orderHints.isEmpty()) {
530
		    org.apache.lucene.search.Sort sort = new Sort();
531
		    SortField[] sortFields = new SortField[orderHints.size()];
532
		    for(int i = 0; i < orderHints.size(); i++) {
533
		    	OrderHint orderHint = orderHints.get(i);
534
		    	switch(orderHint.getSortOrder()) {
535
		    	case ASCENDING:
536
		            sortFields[i] = new SortField(orderHint.getPropertyName(), true);
537
		            break;
538
		    	case DESCENDING:
539
		        default:
540
		    		sortFields[i] = new SortField(orderHint.getPropertyName(),false);
541
		    		
542
		    	}
543
		    }
544
		    sort.setSort(sortFields);
545
		    fullTextQuery.setSort(sort);
546
		    
547
		}
548
	}
549
	
550
	public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {
551
		return list(limit,start,orderHints,null);
552
	}
553
	
554
	public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
555
		Criteria criteria = getSession().createCriteria(type); 
556
		if(limit != null) {
557
			criteria.setFirstResult(start);
558
			criteria.setMaxResults(limit);
559
		}
560
		
561
		addOrder(criteria,orderHints);
562
		List<T> results = (List<T>)criteria.list();
563
		
564
		defaultBeanInitializer.initializeAll(results, propertyPaths);
565
		return results;
566
	}
567

    
568
	public List<T> list(Class<? extends T> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
569
		Criteria criteria = null;
570
		if(clazz == null) {
571
			criteria = getSession().createCriteria(type); 
572
		} else {
573
		    criteria = getSession().createCriteria(clazz);	
574
		} 
575
		
576
		if(limit != null) {
577
			if(start != null) {
578
			    criteria.setFirstResult(start);
579
			} else {
580
				criteria.setFirstResult(0);
581
			}
582
			criteria.setMaxResults(limit);
583
		}
584
		
585
		addOrder(criteria,orderHints);
586
		
587
		List<T> results = (List<T>)criteria.list();
588
		defaultBeanInitializer.initializeAll(results, propertyPaths);
589
		return results; 
590
	}
591
	
592
	public List<T> list(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints) {
593
		return list(type,limit,start,orderHints,null);
594
	}
595
	
596
	public List<T> list(Class<? extends T> type, Integer limit, Integer start) {
597
		return list(type,limit,start,null,null);
598
	}
599
	
600
	public List<T> rows(String tableName, int limit, int start) {
601
		Query query = getSession().createQuery("from " + tableName + " order by uuid");
602
		query.setFirstResult(start);
603
		query.setMaxResults(limit);
604
		List<T> result = query.list();
605
		return result;
606
	}
607
	
608
	public Class<T> getType() {
609
		return type;
610
	}
611
	
612
	protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){
613
		if(pageSize != null) {
614
	    	query.setMaxResults(pageSize);
615
		    if(pageNumber != null) {
616
		    	query.setFirstResult(pageNumber * pageSize);
617
		    } else {
618
		    	query.setFirstResult(0);
619
		    }
620
		}
621
	}
622
	
623
	protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageNumber){
624
		if(pageSize != null) {
625
	    	query.setMaxResults(pageSize);
626
		    if(pageNumber != null) {
627
		    	query.setFirstResult(pageNumber * pageSize);
628
		    } else {
629
		    	query.setFirstResult(0);
630
		    }
631
		}
632
	}
633
	
634
	public int count(T example, Set<String> includeProperties) {
635
		Criteria criteria = getSession().createCriteria(example.getClass());
636
		addExample(criteria,example,includeProperties);
637
		
638
		criteria.setProjection(Projections.rowCount());
639
		return (Integer)criteria.uniqueResult();
640
	}
641
	
642
	protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {
643
		if(includeProperties != null && !includeProperties.isEmpty()) {
644
		    criteria.add(Example.create(example).setPropertySelector(new PropertySelectorImpl(includeProperties)));
645
		    ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(example.getClass());
646
		    for(String property : includeProperties) {  
647
		        Type type  = classMetadata.getPropertyType(property);
648
		        if(type.isEntityType()) {
649
				    try {
650
					    Field field = ReflectionUtils.findField(example.getClass(), property);
651
					    field.setAccessible(true);
652
					    Object value =  field.get(example);
653
					    if(value != null) {
654
			    	        criteria.add(Restrictions.eq(property,value));
655
					    } else {
656
					    	criteria.add(Restrictions.isNull(property));
657
					    }
658
				    } catch (SecurityException se) {
659
					    throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, se);
660
				    } catch (HibernateException he) {
661
					    throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);
662
				    } catch (IllegalArgumentException iae) {
663
					    throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);
664
				    } catch (IllegalAccessException ie) {
665
					    throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);
666
				    }
667
		    	
668
		        }
669
		    }
670
		} else {
671
			criteria.add(Example.create(example));
672
		}
673
	}
674
	
675
	
676
	protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {
677
    	Criteria criteria = null;
678

    
679
    	if(clazz == null) {
680
    		criteria = getSession().createCriteria(type);
681
    	} else {
682
    		criteria = getSession().createCriteria(clazz);
683
    	}
684

    
685
    	if (queryString != null) {
686
    		if(matchmode == null) {
687
    			criteria.add(Restrictions.ilike(param, queryString));
688
    		} else if(matchmode == MatchMode.BEGINNING) {
689
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));
690
    		} else if(matchmode == MatchMode.END) {
691
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));
692
    		} else if(matchmode == MatchMode.EXACT) {
693
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));
694
    		} else {
695
    			criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));
696
    		}
697
    	}
698
    	
699
    	addCriteria(criteria, criterion);
700
    	
701
    	criteria.setProjection(Projections.rowCount());    	
702

    
703
    	List<T> result = criteria.list();
704
    	return (Integer)criteria.uniqueResult();
705
	}
706

    
707
	
708
	public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
709
		Criteria criteria = getSession().createCriteria(example.getClass());
710
		addExample(criteria,example,includeProperties);
711
		
712
		if(limit != null) {
713
			if(start != null) {
714
			    criteria.setFirstResult(start);
715
			} else {
716
				criteria.setFirstResult(0);
717
			}
718
			criteria.setMaxResults(limit);
719
		}
720
		
721
		addOrder(criteria,orderHints);
722
		
723
		List<T> results = (List<T>)criteria.list();
724
		defaultBeanInitializer.initializeAll(results, propertyPaths);
725
		return results; 
726
	}
727
	
728
	private class PropertySelectorImpl implements PropertySelector {
729

    
730
		private Set<String> includeProperties;
731
		/**
732
		 * 
733
		 */
734
		private static final long serialVersionUID = -3175311800911570546L;
735

    
736
		public PropertySelectorImpl(Set<String> includeProperties) {
737
			this.includeProperties = includeProperties;
738
		}
739

    
740
		public boolean include(Object propertyValue, String propertyName,	Type type) {
741
			if(includeProperties.contains(propertyName)) {
742
				return true;
743
			} else {
744
				return false;
745
			}
746
		}
747
		
748
	}
749
}
(3-3/20)