1 package org.hibernate.criterion; 3 4 import java.util.ArrayList ; 5 import java.util.HashSet ; 6 import java.util.List ; 7 import java.util.Set ; 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 31 32 public class Example implements Criterion { 33 34 private final Object entity; 35 private final Set excludedProperties = new HashSet (); 36 private PropertySelector selector; 37 private boolean isLikeEnabled; 38 private boolean isIgnoreCaseEnabled; 39 private MatchMode matchMode; 40 41 45 46 public static interface PropertySelector { 47 public boolean include(Object propertyValue, String 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 object, String propertyName, Type type) { 56 return true; 57 } 58 } 59 60 static final class NotNullPropertySelector implements PropertySelector { 61 public boolean include(Object object, String propertyName, Type type) { 62 return object!=null; 63 } 64 } 65 66 static final class NotNullOrZeroPropertySelector implements PropertySelector { 67 public boolean include(Object object, String propertyName, Type type) { 68 return object!=null && ( 69 !(object instanceof Number ) || ( (Number ) object ).longValue()!=0 70 ); 71 } 72 } 73 74 77 public Example setPropertySelector(PropertySelector selector) { 78 this.selector = selector; 79 return this; 80 } 81 82 85 public Example excludeZeroes() { 86 setPropertySelector(NOT_NULL_OR_ZERO); 87 return this; 88 } 89 90 93 public Example excludeNone() { 94 setPropertySelector(ALL); 95 return this; 96 } 97 98 101 public Example enableLike(MatchMode matchMode) { 102 isLikeEnabled = true; 103 this.matchMode = matchMode; 104 return this; 105 } 106 107 110 public Example enableLike() { 111 return enableLike(MatchMode.EXACT); 112 } 113 114 117 public Example ignoreCase() { 118 isIgnoreCaseEnabled = true; 119 return this; 120 } 121 122 125 public Example excludeProperty(String name) { 126 excludedProperties.add(name); 127 return this; 128 } 129 130 136 public static Example create(Object entity) { 137 if (entity==null) throw new NullPointerException ("null example"); 138 return new Example(entity, NOT_NULL); 139 } 140 141 protected Example(Object entity, PropertySelector selector) { 142 this.entity = entity; 143 this.selector = selector; 144 } 145 146 public String toString() { 147 return "example (" + entity + ')'; 148 } 149 150 private boolean isPropertyIncluded(Object value, String name, Type type) { 151 return !excludedProperties.contains(name) && 152 !type.isAssociationType() && 153 selector.include(value, name, type); 154 } 155 156 public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) 157 throws HibernateException { 158 159 StringBuffer buf = new StringBuffer ().append('('); 160 EntityPersister meta = criteriaQuery.getFactory().getEntityPersister( criteriaQuery.getEntityName(criteria) ); 161 String [] propertyNames = meta.getPropertyNames(); 162 Type[] propertyTypes = meta.getPropertyTypes(); 163 Object [] propertyValues = meta.getPropertyValues( entity, getEntityMode(criteria, criteriaQuery) ); 165 for (int i=0; i<propertyNames.length; i++) { 166 Object propertyValue = propertyValues[i]; 167 String 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"); return buf.append(')').toString(); 195 } 196 197 private static final Object [] 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 [] propertyNames = meta.getPropertyNames(); 205 Type[] propertyTypes = meta.getPropertyTypes(); 206 Object [] values = meta.getPropertyValues( entity, getEntityMode(criteria, criteriaQuery) ); 208 List list = new ArrayList (); 209 for (int i=0; i<propertyNames.length; i++) { 210 Object value = values[i]; 211 Type type = propertyTypes[i]; 212 String 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 ( entity.getClass().getName() ); 235 } 236 return result; 237 } 238 239 protected void addPropertyTypedValue(Object value, Type type, List list) { 240 if ( value!=null ) { 241 if ( value instanceof String ) { 242 String string = (String ) 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 path, 253 Object component, 254 AbstractComponentType type, 255 List list, 256 Criteria criteria, 257 CriteriaQuery criteriaQuery) 258 throws HibernateException { 259 260 if (component!=null) { 261 String [] propertyNames = type.getPropertyNames(); 262 Type[] subtypes = type.getSubtypes(); 263 Object [] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) ); 264 for (int i=0; i<propertyNames.length; i++) { 265 Object value = values[i]; 266 Type subtype = subtypes[i]; 267 String 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 propertyName, 282 Object propertyValue, 283 Criteria criteria, 284 CriteriaQuery cq, 285 StringBuffer buf) 286 throws HibernateException { 287 Criterion crit; 288 if ( propertyValue!=null ) { 289 boolean isString = propertyValue instanceof String ; 290 String op = isLikeEnabled && isString ? " like " : "="; 291 crit = new SimpleExpression( propertyName, propertyValue, op, isIgnoreCaseEnabled && isString ); 292 } 293 else { 294 crit = new NullExpression(propertyName); 295 } 296 String 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 path, 303 Object component, 304 AbstractComponentType type, 305 Criteria criteria, 306 CriteriaQuery criteriaQuery, 307 StringBuffer buf) 308 throws HibernateException { 309 310 if (component!=null) { 311 String [] propertyNames = type.getPropertyNames(); 312 Object [] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) ); 313 Type[] subtypes = type.getSubtypes(); 314 for (int i=0; i<propertyNames.length; i++) { 315 String subpath = StringHelper.qualify( path, propertyNames[i] ); 316 Object 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 |