KickJava   Java API By Example, From Geeks To Geeks.

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


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.math.BigDecimal JavaDoc;
25 import java.math.BigInteger JavaDoc;
26 import java.sql.Date JavaDoc;
27 import java.sql.Time JavaDoc;
28 import java.sql.Timestamp JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import org.apache.velocity.context.InternalContextAdapter;
34 import org.apache.velocity.exception.MethodInvocationException;
35 import org.apache.velocity.exception.ParseErrorException;
36 import org.apache.velocity.exception.ResourceNotFoundException;
37 import org.apache.velocity.runtime.directive.Directive;
38 import org.apache.velocity.runtime.parser.node.Node;
39 import org.apache.cayenne.util.Util;
40
41 /**
42  * A custom Velocity directive to describe a ResultSet column. There are the following
43  * possible invocation formats inside the template:
44  *
45  * <pre>
46  * #result(column_name) - e.g. #result('ARTIST_ID')
47  * #result(column_name java_type) - e.g. #result('ARTIST_ID' 'String')
48  * #result(column_name java_type column_alias) - e.g. #result('ARTIST_ID' 'String' 'ID')
49  * #result(column_name java_type column_alias data_row_key) - e.g. #result('ARTIST_ID' 'String' 'ID' 'toArtist.ID')
50  * </pre>
51  *
52  * <p>
53  * 'data_row_key' is needed if SQL 'column_alias' is not appropriate as a DataRow key on
54  * the Cayenne side. One common case when this happens is when a DataRow retrieved from a
55  * query is mapped using joint prefetch keys. In this case DataRow must use DB_PATH
56  * expressions for joint column keys, and their format is incompatible with most databases
57  * alias format.
58  * </p>
59  * <p>
60  * Most common Java types used in JDBC can be specified without a package. This includes
61  * all numeric types, primitives, String, SQL dates, BigDecimal and BigInteger.
62  * </p>
63  *
64  * @author Andrus Adamchik
65  * @since 1.1
66  */

67 public class ResultDirective extends Directive {
68
69     private static final Map JavaDoc typesGuess = new HashMap JavaDoc();
70
71     static {
72         // init default types
73

74         // primitives
75
typesGuess.put("long", Long JavaDoc.class.getName());
76         typesGuess.put("double", Double JavaDoc.class.getName());
77         typesGuess.put("byte", Byte JavaDoc.class.getName());
78         typesGuess.put("boolean", Boolean JavaDoc.class.getName());
79         typesGuess.put("float", Float JavaDoc.class.getName());
80         typesGuess.put("short", Short JavaDoc.class.getName());
81         typesGuess.put("int", Integer JavaDoc.class.getName());
82
83         // numeric
84
typesGuess.put("Long", Long JavaDoc.class.getName());
85         typesGuess.put("Double", Double JavaDoc.class.getName());
86         typesGuess.put("Byte", Byte JavaDoc.class.getName());
87         typesGuess.put("Boolean", Boolean JavaDoc.class.getName());
88         typesGuess.put("Float", Float JavaDoc.class.getName());
89         typesGuess.put("Short", Short JavaDoc.class.getName());
90         typesGuess.put("Integer", Integer JavaDoc.class.getName());
91
92         // other
93
typesGuess.put("String", String JavaDoc.class.getName());
94         typesGuess.put("Date", Date JavaDoc.class.getName());
95         typesGuess.put("Time", Time JavaDoc.class.getName());
96         typesGuess.put("Timestamp", Timestamp JavaDoc.class.getName());
97         typesGuess.put("BigDecimal", BigDecimal JavaDoc.class.getName());
98         typesGuess.put("BigInteger", BigInteger JavaDoc.class.getName());
99     }
100
101     public String JavaDoc getName() {
102         return "result";
103     }
104
105     public int getType() {
106         return LINE;
107     }
108
109     public boolean render(InternalContextAdapter context, Writer JavaDoc writer, Node node)
110             throws IOException JavaDoc, ResourceNotFoundException, ParseErrorException,
111             MethodInvocationException {
112
113         String JavaDoc column = getChildAsString(context, node, 0);
114         if (column == null) {
115             throw new ParseErrorException("Column name expected at line "
116                     + node.getLine()
117                     + ", column "
118                     + node.getColumn());
119         }
120
121         String JavaDoc alias = getChildAsString(context, node, 2);
122         String JavaDoc dataRowKey = getChildAsString(context, node, 3);
123
124         // determine what we want to name this column in a resulting DataRow...
125
String JavaDoc label = (!Util.isEmptyString(dataRowKey)) ? dataRowKey : (!Util
126                 .isEmptyString(alias)) ? alias : null;
127
128         ColumnDescriptor columnDescriptor = new ColumnDescriptor();
129         columnDescriptor.setName(column);
130         columnDescriptor.setLabel(label);
131
132         String JavaDoc type = getChildAsString(context, node, 1);
133         if (type != null) {
134             columnDescriptor.setJavaClass(guessType(type.toString()));
135         }
136
137         // TODO: andrus 6/27/2007 - this is an unofficial jdbcType parameter that is added
138
// temporarily pending CAY-813 implementation for the sake of EJBQL query...
139
Object JavaDoc jdbcType = getChild(context, node, 4);
140         if(jdbcType instanceof Number JavaDoc) {
141             columnDescriptor.setJdbcType(((Number JavaDoc) jdbcType).intValue());
142         }
143
144         writer.write(column);
145
146         // append column alias if needed.
147

148         // Note that if table aliases are used, this logic will result in SQL like
149
// "t0.ARTIST_NAME AS ARTIST_NAME". Doing extra regex matching to handle this
150
// won't probably buy us much.
151
if (!Util.isEmptyString(alias) && !alias.equals(column)) {
152             writer.write(" AS ");
153             writer.write(alias);
154         }
155
156         bindResult(context, columnDescriptor);
157         return true;
158     }
159
160     protected Object JavaDoc getChild(InternalContextAdapter context, Node node, int i)
161             throws MethodInvocationException {
162         return (i >= 0 && i < node.jjtGetNumChildren()) ? node.jjtGetChild(i).value(
163                 context) : null;
164     }
165
166     /**
167      * Returns a directive argument at a given index converted to String.
168      *
169      * @since 1.2
170      */

171     protected String JavaDoc getChildAsString(InternalContextAdapter context, Node node, int i)
172             throws MethodInvocationException {
173         Object JavaDoc value = getChild(context, node, i);
174         return (value != null) ? value.toString() : null;
175     }
176
177     /**
178      * Converts "short" type notation to the fully qualified class name. Right now
179      * supports all major standard SQL types, including primitives. All other types are
180      * expected to be fully qualified, and are not converted.
181      */

182     protected String JavaDoc guessType(String JavaDoc type) {
183         String JavaDoc guessed = (String JavaDoc) typesGuess.get(type);
184         return guessed != null ? guessed : type;
185     }
186
187     /**
188      * Adds value to the list of result columns in the context.
189      */

190     protected void bindResult(
191             InternalContextAdapter context,
192             ColumnDescriptor columnDescriptor) {
193
194         Collection JavaDoc resultColumns = (Collection JavaDoc) context.getInternalUserContext().get(
195                 SQLTemplateProcessor.RESULT_COLUMNS_LIST_KEY);
196
197         if (resultColumns != null) {
198             resultColumns.add(columnDescriptor);
199         }
200     }
201 }
202
Popular Tags