View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.database.function.criteria;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.hibernate.Criteria;
25  import org.hibernate.HibernateException;
26  import org.hibernate.criterion.CriteriaQuery;
27  import org.hibernate.criterion.Criterion;
28  import org.hibernate.criterion.Junction;
29  import org.hibernate.criterion.Order;
30  import org.hibernate.criterion.Restrictions;
31  import org.hibernate.dialect.Dialect;
32  import org.hibernate.engine.TypedValue;
33  import org.seasar.tuigwaa.database.DataTable;
34  import org.seasar.tuigwaa.database.DataTableFactory;
35  import org.seasar.tuigwaa.database.DatabaseUtils;
36  import org.seasar.tuigwaa.database.function.aggregation.HibernateProjectionList;
37  import org.seasar.tuigwaa.database.function.aggregation.IProjectionList;
38  import org.seasar.tuigwaa.model.core.TgwEntity;
39  
40  import com.isenshi.util.UniqueNameGenerator;
41  
42  public class HibernateCriteria implements ICriteria {
43  
44  	private TgwEntity entity_;
45  
46  	private Criteria criteria_;
47  
48  	private Junction junction_;
49  
50  	private String parentName;
51  	
52  	private HibernateCriteria parentHibernateCriteria;
53  
54  	private HibernateProjectionList projList;
55  
56  	private Map subcriteriaCache_ = new HashMap();
57  
58  	private int joinType = Criteria.INNER_JOIN;	
59  	
60  	private UniqueNameGenerator sucriteriaAliasGenerator = new UniqueNameGenerator();
61  
62  	public HibernateCriteria(Criteria criteria) {
63  		this(criteria, null);
64  	}
65  
66  	public HibernateCriteria(Criteria criteria, TgwEntity entity) {
67  		this.criteria_ = criteria;
68  		this.entity_ = entity;
69  	}
70  
71  	public HibernateCriteria(HibernateCriteria originalCriteria,
72  			Junction junction) {
73  		this(originalCriteria, junction, null);
74  		
75  	}
76  
77  	public HibernateCriteria(HibernateCriteria parentCriteria, Junction junction, String parentName){
78  		this.parentHibernateCriteria = parentCriteria;
79  		this.junction_ = junction;
80  		this.parentName = parentName;
81  	}
82  		
83  	public TgwEntity getEntity() {
84  		return entity_;
85  	}
86  
87  	public ICriteria addEq(String field, Object value) {
88  		if (value == null || "".equals(value)) {
89  			return this;
90  		}
91  		addCriterion(Restrictions.eq(toField(field), value));
92  		return this;
93  	}
94  
95  	public ICriteria addLe(String field, Object value) {
96  		if (value == null || "".equals(value)) {
97  			return this;
98  		}
99  		addCriterion(Restrictions.le(toField(field), value));
100 		return this;
101 	}
102 
103 	public ICriteria addGe(String field, Object value) {
104 		if (value == null || "".equals(value)) {
105 			return this;
106 		}
107 		addCriterion(Restrictions.ge(toField(field), value));
108 		return this;
109 	}
110 
111 	public ICriteria addGt(String field, Object value) {
112 		if (value == null || "".equals(value)) {
113 			return this;
114 		}
115 		addCriterion(Restrictions.gt(toField(field), value));
116 		return this;
117 	}
118 
119 	public ICriteria addLt(String field, Object value) {
120 		if (value == null || "".equals(value)) {
121 			return this;
122 		}
123 		addCriterion(Restrictions.lt(toField(field), value));
124 		return this;
125 	}
126 
127 	public ICriteria addNe(String field, Object value) {
128 		if (value == null || "".equals(value)) {
129 			return this;
130 		}
131 		addCriterion(Restrictions.ne(toField(field), value));
132 		return this;
133 	}
134 
135 	public ICriteria addLike(String field, Object value) {
136 		if (value == null || "".equals(value)) {
137 			return this;
138 		}
139 		
140 		if(DatabaseUtils.isEscapeClauseNeeded()){// temporary			
141 			addCriterion(new LikeExpression(toField(field),value,new Character('//'),false));			
142 		}else{
143 			addCriterion(Restrictions.like(toField(field), value));			
144 		}
145 		return this;
146 	}
147 
148 	public ICriteria addBetween(String field, Object value) {
149 		if (value == null || "".equals(value)) {
150 			return this;
151 		}
152 		Object[] array = (Object[]) value;
153 		addCriterion(Restrictions.between(toField(field), array[0], array[1]));
154 		return this;
155 	}
156 
157 	public ICriteria addIsNull(String field) {
158 		// using or LogicaionExpression
159 		Criterion crit = Restrictions.or(Restrictions.isNull(toField(field)),
160 				Restrictions.eq(toField(field), null));
161 		addCriterion(crit);
162 		// addCriterion(Restrictions.isNull(field));
163 		return this;
164 	}
165 
166 	public ICriteria addIsNotNull(String field) {
167 		addCriterion(Restrictions.isNotNull(toField(field)));
168 		return this;
169 	}
170 
171 	public ICriteria createCriteria(String field) {
172 		return createCriteria(field, null);
173 	}
174 
175 	public ICriteria createCriteria(String field, String alias) {
176 		if (alias == null) {
177 			alias = sucriteriaAliasGenerator.nextUniqueName(field);
178 		}
179 		if (criteria_ == null) { //disjunction 
180 			parentHibernateCriteria.createCriteria(field, alias);
181 			return new HibernateCriteria(this, junction_, toField(field));
182 		} else {
183 			ICriteria icriteria = (ICriteria) subcriteriaCache_.get(field);
184 			if (icriteria == null) {
185 				Criteria criteria = criteria_.createCriteria(field, alias,joinType);
186 				icriteria = new HibernateCriteria(criteria);
187 				subcriteriaCache_.put(field, icriteria);
188 				((HibernateCriteria) icriteria)
189 						.setSucriteriaAliasGenerator(sucriteriaAliasGenerator);
190 				return icriteria;
191 			} else {
192 				return icriteria;
193 			}
194 		}
195 	}
196 
197 	public void setSucriteriaAliasGenerator(UniqueNameGenerator generator) {
198 		this.sucriteriaAliasGenerator = generator;
199 	}
200 
201 	public ICriteria setProjection(IProjectionList projectionList) {
202 		projList = (HibernateProjectionList) projectionList;
203 		criteria_.setProjection(projList.getProjectionList());
204 		return this;
205 	}
206 
207 	public ICriteria addOrder(String field, boolean isDesc) {
208 		if (entity_ != null && entity_.isAggregation()) {
209 			return this; // do nothing
210 		}
211 		if (projList != null && !projList.hasAlias(field)) {
212 			return this;
213 		}
214 		if (isDesc) {
215 			criteria_.addOrder(Order.desc(field));
216 		} else {
217 			criteria_.addOrder(Order.asc(field));
218 		}
219 		return this;
220 	}
221 
222 	public ICriteria disjunction() {
223 		junction_ = Restrictions.disjunction();
224 		addCriterion(junction_);
225 		return new HibernateCriteria(this, junction_);
226 	}
227 
228 	public DataTable list() {
229 		if (criteria_ == null) {
230 			throw new RuntimeException("Illegal operation.");
231 		}
232 		List data = criteria_.list();
233 		data = doConvert(data);
234 		return DataTableFactory.create(entity_, data);
235 	}
236 
237 	public ICriteria setMaxResult(int maxResult) {
238 		if (projList != null || entity_.isAggregation()) {
239 			return this;
240 		}
241 		criteria_.setMaxResults(maxResult);
242 		return this;
243 	}
244 
245 	public ICriteria setFirstResult(int firstResult) {
246 		if (entity_.isAggregation()) {
247 			return this;
248 		}
249 		criteria_.setFirstResult(firstResult);
250 		return this;
251 	}
252 
253 	public void setJoinType(int joinType) {
254 		this.joinType = joinType;
255 	}	
256 	
257 	
258 	// [Start] ----- Private Method ------
259 
260 	private List doConvert(List data) {
261 		if (data == null || !entity_.isAggregation()
262 				|| !projList.hasExtendedColumn()) {
263 			return data;
264 		}
265 		List list = new ArrayList();
266 		Iterator itr = data.iterator();
267 		while (itr.hasNext()) {
268 			Object[] src = (Object[]) itr.next();
269 			Object[] target = new Object[entity_.getAllFieldList().size()];
270 			int pos = 0;
271 			for (int i = 0; i < src.length;) {
272 				boolean first = true;
273 				int columnNum = projList.getColumnNum(pos);
274 				for (int j = 0; j < columnNum; j++) {
275 					if (first) {
276 						target[pos] = src[i++];
277 						first = false;
278 					} else {
279 						target[pos] = target[pos] + "/" + src[i++];
280 					}
281 				}
282 				pos++;
283 			}
284 			list.add(target);
285 		}
286 		return list;
287 	}
288 
289 	private void addCriterion(Criterion criterion) {
290 		if (criteria_ != null) {
291 			criteria_.add(criterion);
292 		} else {
293 			junction_.add(criterion);
294 		}
295 	}
296 	
297 	private String toField(String field){
298 		if(parentName != null){
299 			return parentName + "." + field;
300 		}
301 		return field;
302 	}
303 	
304 	/*
305 	 * temporary fix until update to hibernate 3.2
306 	 */
307 	private class LikeExpression implements Criterion{
308 				
309 		private static final long serialVersionUID = 486881911885233037L;
310 		
311 		private final String propertyName;
312 		private final Object value;
313 		private final Character escapeChar;
314 		private final boolean ignoreCase;
315 		
316 		protected LikeExpression(String propertyName,Object value,Character escapeChar,boolean ignoreCase) {
317 			this.propertyName = propertyName;
318 			this.value = value;
319 			this.escapeChar = escapeChar;
320 			this.ignoreCase = ignoreCase;
321 		}
322 		
323 		public String toSqlString(Criteria criteria,CriteriaQuery criteriaQuery) throws HibernateException {
324 			Dialect dialect = criteriaQuery.getFactory().getDialect();
325 			String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, propertyName );
326 			if ( columns.length != 1 ) {
327 				throw new HibernateException( "Like may only be used with single-column properties" );
328 			}
329 			String lhs = ignoreCase? dialect.getLowercaseFunction() + '(' + columns[0] + ')': columns[0];
330 			return lhs + " like ?" + ( escapeChar == null ? "" : " escape \'" + escapeChar + "\'" );			
331 		}
332 		
333 		public TypedValue[] getTypedValues(Criteria criteria,CriteriaQuery criteriaQuery) throws HibernateException {
334 			return new TypedValue[] {
335 					criteriaQuery.getTypedValue( criteria, propertyName, value.toString().toLowerCase() )
336 			};
337 		}
338 	}		
339 }