KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > access > jdbc > SQLTemplateProcessor


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.access.jdbc;
21
22 import java.io.StringReader JavaDoc;
23 import java.io.StringWriter JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28
29 import org.apache.cayenne.CayenneRuntimeException;
30 import org.apache.velocity.VelocityContext;
31 import org.apache.velocity.context.InternalContextAdapterImpl;
32 import org.apache.velocity.runtime.RuntimeConstants;
33 import org.apache.velocity.runtime.RuntimeInstance;
34 import org.apache.velocity.runtime.log.NullLogSystem;
35 import org.apache.velocity.runtime.parser.ParseException;
36 import org.apache.velocity.runtime.parser.node.SimpleNode;
37
38 /**
39  * Processor for SQL velocity templates.
40  *
41  * @see org.apache.cayenne.query.SQLTemplate
42  * @since 1.1
43  * @author Andrus Adamchik
44  */

45 class SQLTemplateProcessor {
46
47     private static RuntimeInstance sharedRuntime;
48
49     static final String JavaDoc BINDINGS_LIST_KEY = "bindings";
50     static final String JavaDoc RESULT_COLUMNS_LIST_KEY = "resultColumns";
51     static final String JavaDoc HELPER_KEY = "helper";
52
53     private static final SQLTemplateRenderingUtils sharedUtils = new SQLTemplateRenderingUtils();
54
55     RuntimeInstance velocityRuntime;
56     SQLTemplateRenderingUtils renderingUtils;
57
58     static {
59         initVelocityRuntime();
60     }
61
62     private static void initVelocityRuntime() {
63         // init static velocity engine
64
sharedRuntime = new RuntimeInstance();
65
66         // set null logger
67
sharedRuntime.addProperty(
68                 RuntimeConstants.RUNTIME_LOG_LOGSYSTEM,
69                 new NullLogSystem());
70
71         sharedRuntime.addProperty(
72                 RuntimeConstants.RESOURCE_MANAGER_CLASS,
73                 SQLTemplateResourceManager.class.getName());
74         sharedRuntime.addProperty("userdirective", BindDirective.class.getName());
75         sharedRuntime.addProperty("userdirective", BindEqualDirective.class.getName());
76         sharedRuntime.addProperty("userdirective", BindNotEqualDirective.class.getName());
77         sharedRuntime.addProperty("userdirective", BindObjectEqualDirective.class.getName());
78         sharedRuntime.addProperty("userdirective", BindObjectNotEqualDirective.class.getName());
79         sharedRuntime.addProperty("userdirective", ResultDirective.class.getName());
80         sharedRuntime.addProperty("userdirective", ChainDirective.class.getName());
81         sharedRuntime.addProperty("userdirective", ChunkDirective.class.getName());
82         try {
83             sharedRuntime.init();
84         }
85         catch (Exception JavaDoc ex) {
86             throw new CayenneRuntimeException(
87                     "Error setting up Velocity RuntimeInstance.",
88                     ex);
89         }
90     }
91
92     SQLTemplateProcessor() {
93         this.velocityRuntime = sharedRuntime;
94         this.renderingUtils = sharedUtils;
95     }
96
97     SQLTemplateProcessor(RuntimeInstance velocityRuntime,
98             SQLTemplateRenderingUtils renderingUtils) {
99         this.velocityRuntime = velocityRuntime;
100         this.renderingUtils = renderingUtils;
101     }
102
103     /**
104      * Builds and returns a SQLStatement based on SQL template and a set of parameters.
105      * During rendering, VelocityContext exposes the following as variables: all
106      * parameters in the map, {@link SQLTemplateRenderingUtils} as a "helper" variable and
107      * SQLStatement object as "statement" variable.
108      */

109     SQLStatement processTemplate(String JavaDoc template, Map JavaDoc parameters) throws Exception JavaDoc {
110         // have to make a copy of parameter map since we are gonna modify it..
111
Map JavaDoc internalParameters = (parameters != null && !parameters.isEmpty())
112                 ? new HashMap JavaDoc(parameters)
113                 : new HashMap JavaDoc(3);
114
115         List JavaDoc bindings = new ArrayList JavaDoc();
116         List JavaDoc results = new ArrayList JavaDoc();
117         internalParameters.put(BINDINGS_LIST_KEY, bindings);
118         internalParameters.put(RESULT_COLUMNS_LIST_KEY, results);
119         internalParameters.put(HELPER_KEY, renderingUtils);
120
121         String JavaDoc sql = buildStatement(
122                 new VelocityContext(internalParameters),
123                 template,
124                 parameters);
125
126         ParameterBinding[] bindingsArray = new ParameterBinding[bindings.size()];
127         bindings.toArray(bindingsArray);
128
129         ColumnDescriptor[] resultsArray = new ColumnDescriptor[results.size()];
130         results.toArray(resultsArray);
131
132         return new SQLStatement(sql, resultsArray, bindingsArray);
133     }
134
135     String JavaDoc buildStatement(VelocityContext context, String JavaDoc template, Map JavaDoc parameters)
136             throws Exception JavaDoc {
137         // Note: this method is a reworked version of
138
// org.apache.velocity.app.Velocity.evaluate(..)
139
// cleaned up to avoid using any Velocity singletons
140

141         StringWriter JavaDoc out = new StringWriter JavaDoc(template.length());
142         SimpleNode nodeTree = null;
143
144         try {
145             nodeTree = velocityRuntime.parse(new StringReader JavaDoc(template), template);
146         }
147         catch (ParseException pex) {
148             throw new CayenneRuntimeException("Error parsing template '"
149                     + template
150                     + "' : "
151                     + pex.getMessage());
152         }
153
154         if (nodeTree == null) {
155             throw new CayenneRuntimeException("Error parsing template " + template);
156         }
157
158         // ... not sure what InternalContextAdapter is for...
159
InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
160         ica.pushCurrentTemplateName(template);
161
162         try {
163             nodeTree.init(ica, velocityRuntime);
164             nodeTree.render(ica, out);
165             return out.toString();
166         }
167         finally {
168             ica.popCurrentTemplateName();
169         }
170     }
171 }
172
Popular Tags