KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > website > generic > model > hibernate > AbstractHqlModelBuilder


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.website.generic.model.hibernate;
25
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collections JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.regex.Matcher JavaDoc;
32 import java.util.regex.Pattern JavaDoc;
33
34 import javax.servlet.http.HttpServletRequest JavaDoc;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.hibernate.Query;
39 import org.hibernate.SessionFactory;
40 import org.riotfamily.cachius.spring.CacheableController;
41 import org.riotfamily.common.collection.FlatMap;
42 import org.riotfamily.common.util.FormatUtils;
43 import org.riotfamily.riot.hibernate.support.HibernateSupport;
44 import org.riotfamily.riot.hibernate.support.HibernateUtils;
45 import org.riotfamily.website.cache.CacheInvalidationAdvice;
46 import org.riotfamily.website.generic.model.CacheableModelBuilder;
47 import org.springframework.beans.factory.BeanFactoryUtils;
48 import org.springframework.beans.factory.InitializingBean;
49 import org.springframework.context.ApplicationContext;
50 import org.springframework.context.ApplicationContextAware;
51 import org.springframework.util.ClassUtils;
52 import org.springframework.util.StringUtils;
53
54
55 /**
56  * ModelBuilder that builds a model by executing a hibernate query.
57  * Named parameters may be added to the HQL query which will be resolved using
58  * a {@link ParameterResolver}.
59  */

60 public abstract class AbstractHqlModelBuilder extends HibernateSupport
61         implements CacheableModelBuilder,
62         ApplicationContextAware, InitializingBean {
63
64     public static final String JavaDoc CACHE_ETERNAL_STRING = "eternal";
65
66     private static final Pattern JavaDoc PARAM_PATTERN = Pattern.compile("\\:([._\\w]+)");
67     
68     private Log log = LogFactory.getLog(AbstractHqlModelBuilder.class);
69
70     private ApplicationContext applicationContext;
71
72     protected String JavaDoc modelKey;
73
74     private String JavaDoc hql;
75
76     private ArrayList JavaDoc params = new ArrayList JavaDoc();
77
78     private List JavaDoc parameterResolvers;
79
80     private boolean tagCacheItems = true;
81
82     private long timeToLive = CacheableController.CACHE_ETERNALLY;
83
84     public AbstractHqlModelBuilder() {
85     }
86
87     public AbstractHqlModelBuilder(SessionFactory sessionFactory) {
88         setSessionFactory(sessionFactory);
89     }
90
91     public void setApplicationContext(ApplicationContext applicationContext) {
92         this.applicationContext = applicationContext;
93     }
94
95     /**
96      * Sets the key under which the query result will be put into the model.
97      */

98     public void setModelKey(String JavaDoc modelKey) {
99         this.modelKey = modelKey;
100     }
101     
102     protected String JavaDoc getModelKey(Query query) {
103         if (modelKey == null) {
104             modelKey = generateModelKey(query);
105             log.info("Generated model key is " + modelKey);
106         }
107         return modelKey;
108     }
109     
110     protected String JavaDoc generateModelKey(Query query) {
111         Class JavaDoc clazz = getResultClass(query);
112         return StringUtils.uncapitalize(ClassUtils.getShortName(clazz));
113     }
114
115     protected Class JavaDoc getResultClass(Query query) {
116         return query.getReturnTypes()[0].getReturnedClass();
117     }
118     
119     /**
120      * Sets the HQL query to be executed.
121      */

122     public void setHql(String JavaDoc hql) {
123         this.hql = hql;
124     }
125
126     protected String JavaDoc getHql() {
127         return this.hql;
128     }
129
130     /**
131      * Sets a list of {@link ParameterResolver ParameterResolver}s which
132      * are used to resolve named parameters found in the HQL query.
133      */

134     public void setParameterResolvers(List JavaDoc parameterResolvers) {
135         this.parameterResolvers = parameterResolvers;
136     }
137
138     /**
139      * Sets whether the current cache item should be tagged.
140      * Default is <code>true</code>.
141      */

142     public void setTagCacheItems(boolean tagCacheItems) {
143         this.tagCacheItems = tagCacheItems;
144     }
145
146     /**
147      * Sets how long the result should be cached.
148      */

149     public void setTtlPeriod(String JavaDoc timeToLive) {
150         if (!StringUtils.hasText(timeToLive)) {
151             return;
152         }
153         timeToLive = StringUtils.trimTrailingWhitespace(timeToLive);
154         if (timeToLive.equalsIgnoreCase(CACHE_ETERNAL_STRING)) {
155             this.timeToLive = CacheableController.CACHE_ETERNALLY;
156         }
157         else {
158             this.timeToLive = FormatUtils.parseMillis(timeToLive);
159         }
160     }
161
162     public void afterPropertiesSet() throws Exception JavaDoc {
163         if (getSessionFactory() == null) {
164             setSessionFactory((SessionFactory)
165                     BeanFactoryUtils.beanOfTypeIncludingAncestors(
166                     applicationContext, SessionFactory.class));
167         }
168
169         if (parameterResolvers == null) {
170             parameterResolvers = Collections.EMPTY_LIST;
171         }
172
173         Matcher JavaDoc matcher = PARAM_PATTERN.matcher(hql);
174         while (matcher.find()) {
175             String JavaDoc param = matcher.group(1);
176             params.add(new Param(param, getParameterResolver(param)));
177         }
178     }
179
180     /**
181      * Returns a ParameterResolver for the parameter with the given name.
182      * If no matching resolver is found a new {@link DefaultParameterResolver}
183      * is created.
184      */

185     protected ParameterResolver getParameterResolver(String JavaDoc param) {
186         Iterator JavaDoc it = parameterResolvers.iterator();
187         while (it.hasNext()) {
188             ParameterResolver resolver = (ParameterResolver) it.next();
189             if (resolver.accept(param)) {
190                 return resolver;
191             }
192         }
193
194         DefaultParameterResolver resolver = new DefaultParameterResolver();
195         resolver.setParam(param);
196         return resolver;
197     }
198
199     /**
200      * Returns <code>0</code>, if <code>cacheEternally</code> is set to
201      * <code>false</code>, or <code>CacheableModelBuilder.CACHE_ETERNALLY</code>
202      * otherwise. Subclasses may override this method to support modification
203      * based caching.
204      * @see org.riotfamily.website.generic.model.CacheableModelBuilder#getTimeToLive()
205      */

206     public long getTimeToLive() {
207         return this.timeToLive;
208     }
209
210     /**
211      * Returns <code>System.currentTimeMillis()</code>.
212      * Subclasses may override this method to support modification based caching.
213      * Since a database lookup might be nearly as expensive as building the
214      * actual model you might want to consider using item-tagging in conjunction
215      * with a {@link CacheInvalidationAdvice} instead.
216      */

217     public long getLastModified(HttpServletRequest JavaDoc request) {
218         return System.currentTimeMillis();
219     }
220
221     public Map JavaDoc buildModel(final HttpServletRequest JavaDoc request) {
222         HibernateUtils.enableLiveModeFilterIfNecessary(getSession());
223         Query query = createQuery(hql);
224         log.debug("Query: " + query.getQueryString());
225         setParameters(query, request);
226         Object JavaDoc result = getResult(query);
227         if (tagCacheItems) {
228             tagResult(query, result, request);
229         }
230         FlatMap model = new FlatMap();
231         model.put(getModelKey(query), result);
232         return model;
233     }
234     
235     protected abstract Object JavaDoc getResult(Query query);
236     
237     protected void tagResult(Query query, Object JavaDoc result,
238             HttpServletRequest JavaDoc request) {
239         
240     }
241     
242     protected void setParameters(Query query, HttpServletRequest JavaDoc request) {
243         Iterator JavaDoc it = params.iterator();
244         while (it.hasNext()) {
245             Param param = (Param) it.next();
246             Object JavaDoc value = param.getValue(request);
247             log.debug("Query parameter '" + param.name + "' = " + value);
248             query.setParameter(param.name, value);
249         }
250     }
251
252     public void appendCacheKey(StringBuffer JavaDoc key, HttpServletRequest JavaDoc request) {
253         Iterator JavaDoc it = params.iterator();
254         while (it.hasNext()) {
255             Param param = (Param) it.next();
256             param.appendToCacheKey(request, key);
257         }
258     }
259
260     private class Param {
261
262         private String JavaDoc name;
263
264         private ParameterResolver resolver;
265
266         Param (String JavaDoc name, ParameterResolver resolver) {
267             this.name = name;
268             this.resolver = resolver;
269         }
270
271         void appendToCacheKey(HttpServletRequest JavaDoc request, StringBuffer JavaDoc key) {
272             if (resolver.includeInCacheKey()) {
273                 key.append(name).append('=');
274                 key.append(getValue(request)).append(';');
275             }
276         }
277
278         Object JavaDoc getValue(HttpServletRequest JavaDoc request) {
279             return resolver.getValue(request);
280         }
281     }
282
283 }
Popular Tags