1 /***
2 * Copyright (c) 2003 held jointly by the individual authors.
3 *
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 2.1 of the License, or (at your option)
7 * any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17 * > http://www.gnu.org/copyleft/lesser.html >
18 * http://www.opensource.org/licenses/lgpl-license.php
19 */
20 package net.mlw.vlh.adapter.hibernate.util;
21
22 import java.text.ParseException;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28
29 import net.mlw.vlh.adapter.hibernate.util.setter.DefaultSetter;
30 import net.sf.hibernate.HibernateException;
31 import net.sf.hibernate.Query;
32 import net.sf.hibernate.Session;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 /***
38 * Utility for working with hibernate.
39 *
40 * @author Matthew L. Wilson, Andrej Zachar
41 * @version $Revision: 1.4 $ $Date: 2005/12/16 15:40:12 $
42 */
43 public class StatementBuilder
44 {
45 /*** Commons Logger */
46 private static final Log LOGGER = LogFactory.getFactory().getInstance(StatementBuilder.class);
47
48 private Map setters;
49
50 private Setter defaultSetter = new DefaultSetter();
51
52 /***
53 * Usage of filters: {key} -> :keyName add to query's parameter map keyValue
54 * [key] -> keyValue
55 *
56 * @param hql
57 * @param whereClause
58 * @return Query for ordinary list
59 * @throws HibernateException
60 * @throws ParseException
61 */
62 public Query generate(Session session, StringBuffer hql, Map whereClause, boolean isRemoveEmptyStrings) throws HibernateException,
63 ParseException
64 {
65 if (whereClause == null)
66 {
67 whereClause = Collections.EMPTY_MAP;
68 }
69
70 Map arguments = new HashMap();
71
72
73 for (int i = 0, end = 0, start; ((start = hql.toString().indexOf("/~", end)) >= 0); i++)
74 {
75 end = hql.toString().indexOf("~/", start);
76 String key = hql.substring(start + 2, hql.indexOf(":", start));
77
78 Object value = whereClause.get(key);
79 if (isValuePopulated(value, isRemoveEmptyStrings))
80 {
81 if (LOGGER.isDebugEnabled())
82 {
83 LOGGER.debug("The filter key=[" + key + "] with the value=[" + value + "] is accepted by the hql preprocesor");
84 }
85 hql.replace(start, end + 2, hql.substring(hql.indexOf(":", start) + 1, end));
86 }
87 else
88 {
89 if (LOGGER.isInfoEnabled())
90 {
91 LOGGER.info("The filter key=[" + key + "] is removed from the query by the hql preprocesor.");
92 }
93 hql.replace(start, end + 2, "");
94
95 }
96 end -= start;
97 }
98
99
100 for (int i = 0, end = 0, start; ((start = hql.toString().indexOf('[', end)) >= 0); i++)
101 {
102 end = hql.toString().indexOf(']', start);
103 String key = hql.substring(start + 1, end);
104
105 Object value = whereClause.get(key);
106 hql.replace(start, end + 1, (value == null) ? "" : value.toString());
107 end -= (key.length() + 2);
108 }
109
110
111
112 for (int i = 0, end = 0, start; ((start = hql.toString().indexOf('{', end)) >= 0); i++)
113 {
114 end = hql.toString().indexOf('}', start);
115
116 String key = hql.substring(start + 1, end);
117
118 Object value = whereClause.get(key);
119 if (value == null)
120 {
121 throw new NullPointerException("Property '" + key + "' was not provided.");
122 }
123 arguments.put(key, value);
124 hql.replace(start, end + 1, ":" + key);
125 end -= (key.length() + 2);
126 }
127 if (LOGGER.isDebugEnabled())
128 {
129 LOGGER.debug("The final query is " + hql);
130 }
131 Query query = session.createQuery(hql.toString());
132
133
134 if (setters == null)
135 {
136 for (Iterator keys = arguments.keySet().iterator(); keys.hasNext();)
137 {
138 String key = (String) keys.next();
139 Object value = arguments.get(key);
140 if (value instanceof List)
141 {
142 if (LOGGER.isDebugEnabled())
143 {
144 LOGGER.debug("Setting a paremeterList to the query.");
145 }
146 query.setParameterList(key, ((List) value).toArray());
147 }
148 else
149 {
150 if (LOGGER.isDebugEnabled())
151 {
152 LOGGER.debug("Using the default setter for key=[" + key + "] with the value=[" + value + "]");
153 }
154 getDefaultSetter().set(query, key, value);
155 }
156 }
157 }
158 else
159 {
160 for (Iterator keys = arguments.keySet().iterator(); keys.hasNext();)
161 {
162 String key = (String) keys.next();
163 Object value = arguments.get(key);
164 getSetter(key).set(query, key, value);
165 }
166 }
167
168 return query;
169 }
170
171 /***
172 * @param value
173 * @param isRemoveEmptyStrings Enable/Disable String length checking
174 * @return true - When is it not null and for instances of String is lenght >
175 * 0 as well. false - When is null, or String is ""
176 */
177 private boolean isValuePopulated(Object value, boolean isRemoveEmptyStrings)
178 {
179 if (value == null)
180 {
181 return false;
182 }
183 else
184 {
185 if (isRemoveEmptyStrings && value instanceof String)
186 {
187 return ((String) value).length() > 0;
188 }
189 else
190 {
191 return true;
192 }
193 }
194
195 }
196
197 /***
198 * Generete optimalized query for focusing large amount of data.
199 *
200 * @param session
201 * @param hql
202 * @param whereClause
203 * @param isRemoveEmptyStrings
204 * @param defaultFocusPropertyObjectAlias
205 * @param focusProperty
206 * @return
207 * @throws HibernateException
208 * @throws ParseException
209 */
210 public Query generateForFocus(Session session, StringBuffer hql, Map whereClause, boolean isRemoveEmptyStrings,
211 String defaultFocusPropertyObjectAlias, String focusProperty) throws HibernateException, ParseException
212 {
213 StringBuffer hsqlFocus = new StringBuffer("SELECT ");
214 hsqlFocus.append(defaultFocusPropertyObjectAlias);
215 hsqlFocus.append(focusProperty);
216
217 int indexOfTextFrom = hql.toString().toLowerCase().indexOf(" from ");
218 if (indexOfTextFrom < 0)
219 {
220 indexOfTextFrom = hql.toString().toLowerCase().indexOf("from ");
221 hsqlFocus.append(" ");
222 }
223 if (indexOfTextFrom > -1)
224 {
225 hsqlFocus.append(hql.substring(indexOfTextFrom));
226 return generate(session, hsqlFocus, whereClause, isRemoveEmptyStrings);
227 }
228 else
229 {
230 LOGGER.error("HQL hasn't command FROM!!");
231 return null;
232 }
233 }
234
235 /***
236 * @param setters The setters to set.
237 */
238 public void setSetters(Map setters)
239 {
240 this.setters = setters;
241 }
242
243 public Setter getSetter(String key)
244 {
245 Setter setter = null;
246 if (setters != null)
247 {
248 if (LOGGER.isDebugEnabled())
249 {
250 LOGGER.debug("Using custom setters for key=[" + key + "]");
251 }
252 setter = (Setter) setters.get(key);
253 }
254 else
255 {
256 if (LOGGER.isDebugEnabled())
257 {
258 LOGGER.debug("Using default setter for key=[" + key + "]");
259 }
260 }
261
262 return (setter == null) ? defaultSetter : setter;
263
264 }
265
266 /***
267 * @return Returns the defaultSetter.
268 */
269 public Setter getDefaultSetter()
270 {
271 return defaultSetter;
272 }
273
274 /***
275 * @param defaultSetter The defaultSetter to set.
276 */
277 public void setDefaultSetter(Setter defaultSetter)
278 {
279 this.defaultSetter = defaultSetter;
280 }
281 }