KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > sql > Template


1 //$Id: Template.java,v 1.14 2005/07/14 17:56:46 oneovthafew Exp $
2
package org.hibernate.sql;
3
4 import java.util.HashSet JavaDoc;
5 import java.util.StringTokenizer JavaDoc;
6
7 import org.hibernate.dialect.Dialect;
8 import org.hibernate.util.StringHelper;
9
10 /**
11  * Parses SQL fragments specified in mapping documents
12  *
13  * @author Gavin King
14  */

15 public final class Template {
16
17     private static final java.util.Set JavaDoc KEYWORDS = new HashSet JavaDoc();
18     private static final java.util.Set JavaDoc BEFORE_TABLE_KEYWORDS = new HashSet JavaDoc();
19     private static final java.util.Set JavaDoc FUNCTION_KEYWORDS = new HashSet JavaDoc();
20     static {
21         KEYWORDS.add("and");
22         KEYWORDS.add("or");
23         KEYWORDS.add("not");
24         KEYWORDS.add("like");
25         KEYWORDS.add("is");
26         KEYWORDS.add("in");
27         KEYWORDS.add("between");
28         KEYWORDS.add("null");
29         KEYWORDS.add("select");
30         KEYWORDS.add("distinct");
31         KEYWORDS.add("from");
32         KEYWORDS.add("join");
33         KEYWORDS.add("inner");
34         KEYWORDS.add("outer");
35         KEYWORDS.add("left");
36         KEYWORDS.add("right");
37         KEYWORDS.add("on");
38         KEYWORDS.add("where");
39         KEYWORDS.add("having");
40         KEYWORDS.add("group");
41         KEYWORDS.add("order");
42         KEYWORDS.add("by");
43         KEYWORDS.add("desc");
44         KEYWORDS.add("asc");
45         KEYWORDS.add("limit");
46         KEYWORDS.add("any");
47         KEYWORDS.add("some");
48         KEYWORDS.add("exists");
49         KEYWORDS.add("all");
50         
51         BEFORE_TABLE_KEYWORDS.add("from");
52         BEFORE_TABLE_KEYWORDS.add("join");
53         
54         FUNCTION_KEYWORDS.add("as");
55         FUNCTION_KEYWORDS.add("leading");
56         FUNCTION_KEYWORDS.add("trailing");
57         FUNCTION_KEYWORDS.add("from");
58         FUNCTION_KEYWORDS.add("case");
59         FUNCTION_KEYWORDS.add("when");
60         FUNCTION_KEYWORDS.add("then");
61         FUNCTION_KEYWORDS.add("else");
62         FUNCTION_KEYWORDS.add("end");
63         //for DB2 only:
64
FUNCTION_KEYWORDS.add("current");
65         FUNCTION_KEYWORDS.add("date");
66         FUNCTION_KEYWORDS.add("time");
67         FUNCTION_KEYWORDS.add("timestamp");
68     }
69
70     public static final String JavaDoc TEMPLATE = "$PlaceHolder$";
71
72     private Template() {}
73
74     public static String JavaDoc renderWhereStringTemplate(String JavaDoc sqlWhereString, Dialect dialect) {
75         return renderWhereStringTemplate(sqlWhereString, TEMPLATE, dialect);
76     }
77     
78     /**
79      * Takes the where condition provided in the mapping attribute and interpolates the alias.
80      * Handles subselects, quoted identifiers, quoted strings, expressions, SQL functions,
81      * named parameters.
82      */

83     public static String JavaDoc renderWhereStringTemplate(String JavaDoc sqlWhereString, String JavaDoc placeholder, Dialect dialect) {
84         //TODO: make this a bit nicer
85
String JavaDoc symbols = new StringBuffer JavaDoc()
86             .append("=><!+-*/()',|&`")
87             .append(StringHelper.WHITESPACE)
88             .append( dialect.openQuote() )
89             .append( dialect.closeQuote() )
90             .toString();
91         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(sqlWhereString, symbols, true);
92         
93         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
94         boolean quoted = false;
95         boolean quotedIdentifier = false;
96         boolean beforeTable = false;
97         boolean inFromClause = false;
98         boolean afterFromTable = false;
99         
100         boolean hasMore = tokens.hasMoreTokens();
101         String JavaDoc nextToken = hasMore ? tokens.nextToken() : null;
102         while (hasMore) {
103             String JavaDoc token = nextToken;
104             String JavaDoc lcToken = token.toLowerCase();
105             hasMore = tokens.hasMoreTokens();
106             nextToken = hasMore ? tokens.nextToken() : null;
107             
108             boolean isQuoteCharacter = false;
109             
110             if ( !quotedIdentifier && "'".equals(token) ) {
111                 quoted = !quoted;
112                 isQuoteCharacter = true;
113             }
114             
115             if ( !quoted ) {
116                 
117                 boolean isOpenQuote;
118                 if ( "`".equals(token) ) {
119                     isOpenQuote = !quotedIdentifier;
120                     token = lcToken = isOpenQuote ?
121                         new Character JavaDoc( dialect.openQuote() ).toString() :
122                         new Character JavaDoc( dialect.closeQuote() ).toString();
123                     quotedIdentifier = isOpenQuote;
124                     isQuoteCharacter = true;
125                 }
126                 else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) {
127                     isOpenQuote = true;
128                     quotedIdentifier = true;
129                     isQuoteCharacter = true;
130                 }
131                 else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) {
132                     quotedIdentifier = false;
133                     isQuoteCharacter = true;
134                     isOpenQuote = false;
135                 }
136                 else {
137                     isOpenQuote = false;
138                 }
139                 
140                 if (isOpenQuote) {
141                     result.append(TEMPLATE).append('.');
142                 }
143                 
144             }
145     
146             boolean quotedOrWhitespace = quoted ||
147                 quotedIdentifier ||
148                 isQuoteCharacter ||
149                 Character.isWhitespace( token.charAt(0) );
150             
151             if (quotedOrWhitespace) {
152                 result.append(token);
153             }
154             else if (beforeTable) {
155                 result.append(token);
156                 beforeTable = false;
157                 afterFromTable = true;
158             }
159             else if (afterFromTable) {
160                 if ( !"as".equals(lcToken) ) afterFromTable = false;
161                 result.append(token);
162             }
163             else if ( isNamedParameter(token) ) {
164                 result.append(token);
165             }
166             else if (
167                 isIdentifier(token, dialect) &&
168                 !isFunctionOrKeyword(lcToken, nextToken, dialect)
169             ) {
170                 result.append(placeholder)
171                     .append('.')
172                     .append( dialect.quote(token) );
173             }
174             else {
175                 if ( BEFORE_TABLE_KEYWORDS.contains(lcToken) ) {
176                     beforeTable = true;
177                     inFromClause = true;
178                 }
179                 else if ( inFromClause && ",".equals(lcToken) ) {
180                     beforeTable = true;
181                 }
182                 result.append(token);
183             }
184             
185             if ( //Yuck:
186
inFromClause &&
187                     KEYWORDS.contains(lcToken) && //"as" is not in KEYWORDS
188
!BEFORE_TABLE_KEYWORDS.contains(lcToken)
189             ) {
190                 inFromClause = false;
191             }
192
193         }
194         return result.toString();
195     }
196
197     /**
198      * Takes order by clause provided in the mapping attribute and interpolates the alias.
199      * Handles asc, desc, SQL functions, quoted identifiers.
200      */

201     public static String JavaDoc renderOrderByStringTemplate(String JavaDoc sqlOrderByString, Dialect dialect) {
202         //TODO: make this a bit nicer
203
String JavaDoc symbols = new StringBuffer JavaDoc()
204             .append("=><!+-*/()',|&`")
205             .append(StringHelper.WHITESPACE)
206             .append( dialect.openQuote() )
207             .append( dialect.closeQuote() )
208             .toString();
209         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(sqlOrderByString, symbols, true);
210         
211         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
212         boolean quoted = false;
213         boolean quotedIdentifier = false;
214         
215         boolean hasMore = tokens.hasMoreTokens();
216         String JavaDoc nextToken = hasMore ? tokens.nextToken() : null;
217         while (hasMore) {
218             String JavaDoc token = nextToken;
219             String JavaDoc lcToken = token.toLowerCase();
220             hasMore = tokens.hasMoreTokens();
221             nextToken = hasMore ? tokens.nextToken() : null;
222             
223             boolean isQuoteCharacter = false;
224             
225             if ( !quotedIdentifier && "'".equals(token) ) {
226                 quoted = !quoted;
227                 isQuoteCharacter = true;
228             }
229             
230             if ( !quoted ) {
231                 
232                 boolean isOpenQuote;
233                 if ( "`".equals(token) ) {
234                     isOpenQuote = !quotedIdentifier;
235                     token = lcToken = isOpenQuote ?
236                         new Character JavaDoc( dialect.openQuote() ).toString() :
237                         new Character JavaDoc( dialect.closeQuote() ).toString();
238                     quotedIdentifier = isOpenQuote;
239                     isQuoteCharacter = true;
240                 }
241                 else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) {
242                     isOpenQuote = true;
243                     quotedIdentifier = true;
244                     isQuoteCharacter = true;
245                 }
246                 else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) {
247                     quotedIdentifier = false;
248                     isQuoteCharacter = true;
249                     isOpenQuote = false;
250                 }
251                 else {
252                     isOpenQuote = false;
253                 }
254                 
255                 if (isOpenQuote) {
256                     result.append(TEMPLATE).append('.');
257                 }
258                 
259             }
260     
261             boolean quotedOrWhitespace = quoted ||
262                 quotedIdentifier ||
263                 isQuoteCharacter ||
264                 Character.isWhitespace( token.charAt(0) );
265             
266             if (quotedOrWhitespace) {
267                 result.append(token);
268             }
269             else if (
270                 isIdentifier(token, dialect) &&
271                 !isFunctionOrKeyword(lcToken, nextToken, dialect)
272             ) {
273                 result.append(TEMPLATE)
274                     .append('.')
275                     .append( dialect.quote(token) );
276             }
277             else {
278                 result.append(token);
279             }
280         }
281         return result.toString();
282     }
283     
284     private static boolean isNamedParameter(String JavaDoc token) {
285         return token.startsWith(":");
286     }
287
288     private static boolean isFunctionOrKeyword(String JavaDoc lcToken, String JavaDoc nextToken, Dialect dialect) {
289         return "(".equals(nextToken) ||
290             KEYWORDS.contains(lcToken) ||
291             dialect.getFunctions().containsKey(lcToken) ||
292             FUNCTION_KEYWORDS.contains(lcToken);
293     }
294
295     private static boolean isIdentifier(String JavaDoc token, Dialect dialect) {
296         return token.charAt(0)=='`' || ( //allow any identifier quoted with backtick
297
Character.isLetter( token.charAt(0) ) && //only recognizes identifiers beginning with a letter
298
token.indexOf('.') < 0
299         );
300     }
301
302     
303 }
304
Popular Tags