KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > criterion > Example


1 //$Id: Example.java,v 1.19 2005/02/21 02:46:40 oneovthafew Exp $
2
package org.hibernate.criterion;
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.HashSet JavaDoc;
6 import java.util.List JavaDoc;
7 import java.util.Set JavaDoc;
8
9 import org.hibernate.Criteria;
10 import org.hibernate.EntityMode;
11 import org.hibernate.HibernateException;
12 import org.hibernate.engine.TypedValue;
13 import org.hibernate.persister.entity.EntityPersister;
14 import org.hibernate.type.AbstractComponentType;
15 import org.hibernate.type.Type;
16 import org.hibernate.util.StringHelper;
17
18 /**
19  * Support for query by example.
20  * <pre>
21  * List results = session.createCriteria(Parent.class)
22  * .add( Example.create(parent).ignoreCase() )
23  * .createCriteria("child")
24  * .add( Example.create( parent.getChild() ) )
25  * .list();
26  * </pre>
27  * "Examples" may be mixed and matched with "Expressions" in the same <tt>Criteria</tt>.
28  * @see org.hibernate.Criteria
29  * @author Gavin King
30  */

31
32 public class Example implements Criterion {
33
34     private final Object JavaDoc entity;
35     private final Set JavaDoc excludedProperties = new HashSet JavaDoc();
36     private PropertySelector selector;
37     private boolean isLikeEnabled;
38     private boolean isIgnoreCaseEnabled;
39     private MatchMode matchMode;
40
41     /**
42      * A strategy for choosing property values for inclusion in the query
43      * criteria
44      */

45
46     public static interface PropertySelector {
47         public boolean include(Object JavaDoc propertyValue, String JavaDoc propertyName, Type type);
48     }
49
50     private static final PropertySelector NOT_NULL = new NotNullPropertySelector();
51     private static final PropertySelector ALL = new AllPropertySelector();
52     private static final PropertySelector NOT_NULL_OR_ZERO = new NotNullOrZeroPropertySelector();
53
54     static final class AllPropertySelector implements PropertySelector {
55         public boolean include(Object JavaDoc object, String JavaDoc propertyName, Type type) {
56             return true;
57         }
58     }
59
60     static final class NotNullPropertySelector implements PropertySelector {
61         public boolean include(Object JavaDoc object, String JavaDoc propertyName, Type type) {
62             return object!=null;
63         }
64     }
65
66     static final class NotNullOrZeroPropertySelector implements PropertySelector {
67         public boolean include(Object JavaDoc object, String JavaDoc propertyName, Type type) {
68             return object!=null && (
69                 !(object instanceof Number JavaDoc) || ( (Number JavaDoc) object ).longValue()!=0
70             );
71         }
72     }
73
74     /**
75      * Set the property selector
76      */

77     public Example setPropertySelector(PropertySelector selector) {
78         this.selector = selector;
79         return this;
80     }
81
82     /**
83      * Exclude zero-valued properties
84      */

85     public Example excludeZeroes() {
86         setPropertySelector(NOT_NULL_OR_ZERO);
87         return this;
88     }
89
90     /**
91      * Don't exclude null or zero-valued properties
92      */

93     public Example excludeNone() {
94         setPropertySelector(ALL);
95         return this;
96     }
97
98     /**
99      * Use the "like" operator for all string-valued properties
100      */

101     public Example enableLike(MatchMode matchMode) {
102         isLikeEnabled = true;
103         this.matchMode = matchMode;
104         return this;
105     }
106
107     /**
108      * Use the "like" operator for all string-valued properties
109      */

110     public Example enableLike() {
111         return enableLike(MatchMode.EXACT);
112     }
113
114     /**
115      * Ignore case for all string-valued properties
116      */

117     public Example ignoreCase() {
118         isIgnoreCaseEnabled = true;
119         return this;
120     }
121
122     /**
123      * Exclude a particular named property
124      */

125     public Example excludeProperty(String JavaDoc name) {
126         excludedProperties.add(name);
127         return this;
128     }
129
130     /**
131      * Create a new instance, which includes all non-null properties
132      * by default
133      * @param entity
134      * @return a new instance of <tt>Example</tt>
135      */

136     public static Example create(Object JavaDoc entity) {
137         if (entity==null) throw new NullPointerException JavaDoc("null example");
138         return new Example(entity, NOT_NULL);
139     }
140
141     protected Example(Object JavaDoc entity, PropertySelector selector) {
142         this.entity = entity;
143         this.selector = selector;
144     }
145
146     public String JavaDoc toString() {
147         return "example (" + entity + ')';
148     }
149
150     private boolean isPropertyIncluded(Object JavaDoc value, String JavaDoc name, Type type) {
151         return !excludedProperties.contains(name) &&
152             !type.isAssociationType() &&
153             selector.include(value, name, type);
154     }
155
156     public String JavaDoc toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
157         throws HibernateException {
158
159         StringBuffer JavaDoc buf = new StringBuffer JavaDoc().append('(');
160         EntityPersister meta = criteriaQuery.getFactory().getEntityPersister( criteriaQuery.getEntityName(criteria) );
161         String JavaDoc[] propertyNames = meta.getPropertyNames();
162         Type[] propertyTypes = meta.getPropertyTypes();
163         //TODO: get all properties, not just the fetched ones!
164
Object JavaDoc[] propertyValues = meta.getPropertyValues( entity, getEntityMode(criteria, criteriaQuery) );
165         for (int i=0; i<propertyNames.length; i++) {
166             Object JavaDoc propertyValue = propertyValues[i];
167             String JavaDoc propertyName = propertyNames[i];
168
169             boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
170                 isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] );
171             if (isPropertyIncluded) {
172                 if ( propertyTypes[i].isComponentType() ) {
173                     appendComponentCondition(
174                         propertyName,
175                         propertyValue,
176                         (AbstractComponentType) propertyTypes[i],
177                         criteria,
178                         criteriaQuery,
179                         buf
180                     );
181                 }
182                 else {
183                     appendPropertyCondition(
184                         propertyName,
185                         propertyValue,
186                         criteria,
187                         criteriaQuery,
188                         buf
189                     );
190                 }
191             }
192         }
193         if ( buf.length()==1 ) buf.append("1=1"); //yuck!
194
return buf.append(')').toString();
195     }
196
197     private static final Object JavaDoc[] TYPED_VALUES = new TypedValue[0];
198
199     public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
200     throws HibernateException {
201
202         EntityPersister meta = criteriaQuery.getFactory()
203                 .getEntityPersister( criteriaQuery.getEntityName(criteria) );
204         String JavaDoc[] propertyNames = meta.getPropertyNames();
205         Type[] propertyTypes = meta.getPropertyTypes();
206          //TODO: get all properties, not just the fetched ones!
207
Object JavaDoc[] values = meta.getPropertyValues( entity, getEntityMode(criteria, criteriaQuery) );
208         List JavaDoc list = new ArrayList JavaDoc();
209         for (int i=0; i<propertyNames.length; i++) {
210             Object JavaDoc value = values[i];
211             Type type = propertyTypes[i];
212             String JavaDoc name = propertyNames[i];
213
214             boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
215                 isPropertyIncluded(value, name, type);
216
217             if (isPropertyIncluded) {
218                 if ( propertyTypes[i].isComponentType() ) {
219                     addComponentTypedValues(name, value, (AbstractComponentType) type, list, criteria, criteriaQuery);
220                 }
221                 else {
222                     addPropertyTypedValue(value, type, list);
223                 }
224             }
225         }
226         return (TypedValue[]) list.toArray(TYPED_VALUES);
227     }
228     
229     private EntityMode getEntityMode(Criteria criteria, CriteriaQuery criteriaQuery) {
230         EntityPersister meta = criteriaQuery.getFactory()
231                 .getEntityPersister( criteriaQuery.getEntityName(criteria) );
232         EntityMode result = meta.guessEntityMode(entity);
233         if (result==null) {
234             throw new ClassCastException JavaDoc( entity.getClass().getName() );
235         }
236         return result;
237     }
238
239     protected void addPropertyTypedValue(Object JavaDoc value, Type type, List JavaDoc list) {
240         if ( value!=null ) {
241             if ( value instanceof String JavaDoc ) {
242                 String JavaDoc string = (String JavaDoc) value;
243                 if (isIgnoreCaseEnabled) string = string.toLowerCase();
244                 if (isLikeEnabled) string = matchMode.toMatchString(string);
245                 value = string;
246             }
247             list.add( new TypedValue(type, value, null) );
248         }
249     }
250
251     protected void addComponentTypedValues(
252             String JavaDoc path,
253             Object JavaDoc component,
254             AbstractComponentType type,
255             List JavaDoc list,
256             Criteria criteria,
257             CriteriaQuery criteriaQuery)
258     throws HibernateException {
259
260         if (component!=null) {
261             String JavaDoc[] propertyNames = type.getPropertyNames();
262             Type[] subtypes = type.getSubtypes();
263             Object JavaDoc[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
264             for (int i=0; i<propertyNames.length; i++) {
265                 Object JavaDoc value = values[i];
266                 Type subtype = subtypes[i];
267                 String JavaDoc subpath = StringHelper.qualify( path, propertyNames[i] );
268                 if ( isPropertyIncluded(value, subpath, subtype) ) {
269                     if ( subtype.isComponentType() ) {
270                         addComponentTypedValues(subpath, value, (AbstractComponentType) subtype, list, criteria, criteriaQuery);
271                     }
272                     else {
273                         addPropertyTypedValue(value, subtype, list);
274                     }
275                 }
276             }
277         }
278     }
279
280     protected void appendPropertyCondition(
281         String JavaDoc propertyName,
282         Object JavaDoc propertyValue,
283         Criteria criteria,
284         CriteriaQuery cq,
285         StringBuffer JavaDoc buf)
286     throws HibernateException {
287         Criterion crit;
288         if ( propertyValue!=null ) {
289             boolean isString = propertyValue instanceof String JavaDoc;
290             String JavaDoc op = isLikeEnabled && isString ? " like " : "=";
291             crit = new SimpleExpression( propertyName, propertyValue, op, isIgnoreCaseEnabled && isString );
292         }
293         else {
294             crit = new NullExpression(propertyName);
295         }
296         String JavaDoc critCondition = crit.toSqlString(criteria, cq);
297         if ( buf.length()>1 && critCondition.trim().length()>0 ) buf.append(" and ");
298         buf.append(critCondition);
299     }
300
301     protected void appendComponentCondition(
302         String JavaDoc path,
303         Object JavaDoc component,
304         AbstractComponentType type,
305         Criteria criteria,
306         CriteriaQuery criteriaQuery,
307         StringBuffer JavaDoc buf)
308     throws HibernateException {
309
310         if (component!=null) {
311             String JavaDoc[] propertyNames = type.getPropertyNames();
312             Object JavaDoc[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
313             Type[] subtypes = type.getSubtypes();
314             for (int i=0; i<propertyNames.length; i++) {
315                 String JavaDoc subpath = StringHelper.qualify( path, propertyNames[i] );
316                 Object JavaDoc value = values[i];
317                 if ( isPropertyIncluded( value, subpath, subtypes[i] ) ) {
318                     Type subtype = subtypes[i];
319                     if ( subtype.isComponentType() ) {
320                         appendComponentCondition(
321                             subpath,
322                             value,
323                             (AbstractComponentType) subtype,
324                             criteria,
325                             criteriaQuery,
326                             buf
327                         );
328                     }
329                     else {
330                         appendPropertyCondition(
331                             subpath,
332                             value,
333                             criteria,
334                             criteriaQuery,
335                             buf
336                         );
337                     }
338                 }
339             }
340         }
341     }
342 }
Popular Tags