KickJava   Java API By Example, From Geeks To Geeks.

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


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.IOException JavaDoc;
23 import java.io.Writer JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Iterator JavaDoc;
26
27 import org.apache.velocity.context.InternalContextAdapter;
28 import org.apache.velocity.exception.MethodInvocationException;
29 import org.apache.velocity.exception.ParseErrorException;
30 import org.apache.velocity.exception.ResourceNotFoundException;
31 import org.apache.velocity.runtime.directive.Directive;
32 import org.apache.velocity.runtime.parser.node.Node;
33 import org.apache.cayenne.dba.TypesMapping;
34 import org.apache.cayenne.util.ConversionUtil;
35
36 /**
37  * A custom Velocity directive to create a PreparedStatement parameter text.
38  * There are the following possible invocation formats inside the template:
39  *
40  * <pre>
41  * #bind(value) - e.g. #bind($xyz)
42  * #bind(value jdbc_type_name) - e.g. #bind($xyz 'VARCHAR'). This is the most common and useful form.
43  * #bind(value jdbc_type_name, precision) - e.g. #bind($xyz 'VARCHAR' 2)</pre>
44  *
45  *
46  * <p>Other examples:</p>
47  *
48  * <p><strong>Binding literal parameter value:</strong></p>
49  * <p><code>"WHERE SOME_COLUMN > #bind($xyz)"</code> produces
50  * <code>"WHERE SOME_COLUMN > ?"</code>
51  * and also places the value of the "xyz" parameter in the context "bindings" collection.</p>
52  *
53  * <p><strong>Binding ID column of a DataObject value:</strong></p>
54  * <p><code>"WHERE ID_COL1 = #bind($helper.cayenneExp($xyz, 'db:ID_COL2'))
55  * AND ID_COL2 = #bind($helper.cayenneExp($xyz, 'db:ID_COL2'))"</code>
56  * produces <code>"WHERE ID_COL1 = ? AND ID_COL2 = ?"</code>
57  * and also places the values of id columns of the DataObject parameter "xyz" in the context
58  * "bindings" collection.</p>
59  *
60  * @since 1.1
61  * @author Andrus Adamchik
62  */

63 public class BindDirective extends Directive {
64
65     public String JavaDoc getName() {
66         return "bind";
67     }
68
69     public int getType() {
70         return LINE;
71     }
72
73     /**
74      * Extracts the value of the object property to render and passes
75      * control to {@link #render(InternalContextAdapter, Writer, ParameterBinding)}
76      * to do the actual rendering.
77      */

78     public boolean render(InternalContextAdapter context, Writer JavaDoc writer, Node node)
79         throws
80             IOException JavaDoc,
81             ResourceNotFoundException,
82             ParseErrorException,
83             MethodInvocationException {
84
85         Object JavaDoc value = getChild(context, node, 0);
86         Object JavaDoc type = getChild(context, node, 1);
87         Object JavaDoc precision = getChild(context, node, 2);
88
89         int jdbcType = TypesMapping.NOT_DEFINED;
90         if (type != null) {
91             jdbcType = TypesMapping.getSqlTypeByName(type.toString());
92         }
93         else if (value != null) {
94             jdbcType = TypesMapping.getSqlTypeByJava(value.getClass());
95         }
96
97         if (jdbcType == TypesMapping.NOT_DEFINED) {
98             throw new ParseErrorException(
99                 "Can't determine JDBC type of binding ("
100                     + value
101                     + ", "
102                     + type
103                     + ") at line "
104                     + node.getLine()
105                     + ", column "
106                     + node.getColumn());
107         }
108
109         ParameterBinding binding =
110             new ParameterBinding(value, jdbcType, ConversionUtil.toInt(precision, -1));
111
112         render(context, writer, binding);
113         return true;
114     }
115
116     protected void render(
117         InternalContextAdapter context,
118         Writer JavaDoc writer,
119         ParameterBinding binding)
120         throws IOException JavaDoc {
121
122         bind(context, binding);
123         
124         if (binding.getValue() instanceof Collection JavaDoc) {
125             Collection JavaDoc bindingList = (Collection JavaDoc) binding.getValue();
126             for (Iterator JavaDoc bindingIter = bindingList.iterator(); bindingIter.hasNext(); ) {
127                 
128                 bindingIter.next();
129                 writer.write('?');
130                 
131                 if (bindingIter.hasNext()) {
132                     writer.write(',');
133                 }
134                 
135             }
136         } else {
137             writer.write('?');
138         }
139     }
140
141     protected Object JavaDoc getChild(InternalContextAdapter context, Node node, int i)
142         throws MethodInvocationException {
143         return (i >= 0 && i < node.jjtGetNumChildren())
144             ? node.jjtGetChild(i).value(context)
145             : null;
146     }
147
148     /**
149      * Adds value to the list of bindings in the context.
150      */

151     protected void bind(InternalContextAdapter context, ParameterBinding binding) {
152         Collection JavaDoc bindings =
153             (Collection JavaDoc) context.getInternalUserContext().get(
154                 SQLTemplateProcessor.BINDINGS_LIST_KEY);
155
156         if (bindings != null) {
157             
158             if (binding.getValue() instanceof Collection JavaDoc) {
159                 Collection JavaDoc bindingList = (Collection JavaDoc) binding.getValue();
160                 for (Iterator JavaDoc bindingIter = bindingList.iterator(); bindingIter.hasNext(); ) {
161                     bindings.add(new ParameterBinding(bindingIter.next(), binding.getJdbcType(), binding.getPrecision()));
162                 }
163             } else {
164                 bindings.add(binding);
165             }
166         }
167     }
168 }
169
Popular Tags