1 package org.ocltf.translation.query;
2
3 import java.util.List;
4
5 import org.apache.commons.lang.StringUtils;
6 import org.ocltf.concretesyntax.VariableDeclarationCS;
7 import org.ocltf.concretesyntax.impl.ConcreteSyntaxUtils;
8 import org.ocltf.parser.node.AFeatureCall;
9 import org.ocltf.parser.node.ALogicalExpressionTail;
10 import org.ocltf.parser.node.AOperationContextDeclaration;
11 import org.ocltf.parser.node.APropertyCallExpression;
12 import org.ocltf.parser.node.ARelationalExpressionTail;
13 import org.ocltf.parser.node.AStandardDeclarator;
14 import org.ocltf.parser.node.PRelationalExpression;
15 import org.ocltf.translation.BaseTranslator;
16 import org.ocltf.translation.TranslationUtils;
17
18 /***
19 * Performs translation to the following:
20 * <ul>
21 * <li>
22 * Hibernate-QL
23 * </li>
24 * </ul>
25 * @author Chad Brandon
26 */
27 public class QueryTranslator extends BaseTranslator {
28
29 /***
30 * Used to save the argument names for the operation which represents the
31 * context of the expression being translated.
32 */
33 private List argumentNames = null;
34
35 /***
36 * Contains the select clause of the query.
37 */
38 private StringBuffer selectClause;
39
40 /***
41 * Called by super class to reset any objects.
42 */
43 protected void preProcess() {
44 super.preProcess();
45 this.selectClause = new StringBuffer();
46 this.declaratorCtr = 0;
47 }
48
49 /***
50 * Stores the name of the initial declarator.
51 */
52 private short declaratorCtr;
53
54 /***
55 * True/false whether or not its the initial declarator.
56 * We care about this because we must know what the first one is
57 * for differentiating between the first declarator (the beginning of the query)
58 * and any other declarators (the connecting associations).
59 */
60 protected boolean isInitialDeclarator() {
61 boolean isInitialDeclarator = (this.declaratorCtr <= 0);
62 this.declaratorCtr++;
63 return isInitialDeclarator;
64 }
65
66 /***
67 * Returns true if the name is one of the arguments.
68 *
69 * @return boolean true if its an argument
70 */
71 protected boolean isArgument(String name) {
72 boolean isArgument = this.argumentNames != null;
73 if (isArgument) {
74 isArgument = this.argumentNames.contains(name);
75 }
76 return isArgument;
77 }
78
79 /***
80 * Gets the information about the operation which is the context of this
81 * expression.
82 */
83 public void inAOperationContextDeclaration(AOperationContextDeclaration declaration) {
84 super.inAOperationContextDeclaration(declaration);
85 VariableDeclarationCS[] variableDeclarations =
86 ConcreteSyntaxUtils.getVariableDeclarations(
87 declaration.getOperation());
88
89 this.argumentNames = ConcreteSyntaxUtils.getArgumentNames(variableDeclarations);
90 }
91
92 /***
93 * Helps out with 'includesAll', replaces the {1} in the expression fragment
94 * when a declarator is encountered (i.e. '| <variable name>')
95 */
96 public void inAStandardDeclarator(AStandardDeclarator declarator) {
97 String methodName = "inAStandardDeclarator";
98 if (logger.isDebugEnabled()) {
99 logger.debug(
100 "performing "
101 + methodName
102 + " with declarator --> "
103 + declarator);
104 }
105
106 String temp = this.selectClause.toString();
107
108 String declaratorName =
109 ConcreteSyntaxUtils.getVariableDeclarations(declarator)[0].getName();
110
111
112 short replacement = 1;
113 if (this.isInitialDeclarator()) {
114
115 replacement = 0;
116 }
117
118
119 temp =
120 TranslationUtils.replacePattern(
121 temp,
122 String.valueOf(replacement),
123 declaratorName);
124 this.selectClause = new StringBuffer(temp);
125 }
126
127 /***
128 * Override to handle any propertyCall expressions (
129 * i.e. exists(<expression>), select(<expression>, etc.)
130 */
131 public void inAPropertyCallExpression(APropertyCallExpression expression) {
132
133 this.handleTranslationFragment(expression);
134 }
135
136 /***
137 * Override to deal with logical 'and, 'or', 'xor, ... expressions.
138 */
139 public void inALogicalExpressionTail(ALogicalExpressionTail logicalExpressionTail) {
140 this.handleTranslationFragment(logicalExpressionTail);
141 }
142
143 /***
144 * Override to deal with relational '<, '>', '=', ... expressions.
145 */
146 public void inARelationalExpressionTail(ARelationalExpressionTail relationalExpressionTail) {
147 this.handleTranslationFragment(relationalExpressionTail);
148 }
149
150 /***
151 * Checks to see if the replacement is an argument and if so replaces the
152 * {index} in the fragment with the 'argument' fragment from the template.
153 * Otherwise replaces the {index} with the passed in replacement value.
154 *
155 * @param fragment the fragment to perform replacement.
156 * @param replacement the replacement string
157 * @param index the index in the string to replace.
158 * @return String the fragment with any replacements.
159 */
160 protected String replaceFragment(
161 String fragment,
162 String replacement,
163 int index) {
164 fragment = StringUtils.trimToEmpty(fragment);
165 replacement = StringUtils.trimToEmpty(replacement);
166
167
168 if (this.isArgument(replacement)) {
169 replacement = this.getTranslationFragment("argument");
170 }
171 fragment =
172 TranslationUtils.replacePattern(
173 fragment,
174 String.valueOf(index),
175 replacement);
176 return fragment;
177 }
178
179 /***
180 * Handles any final processing.
181 */
182 protected void postProcess() {
183 super.postProcess();
184
185 String selectClauseTail =
186 this.getTranslationFragment("selectClauseTail");
187 String existingExpression =
188 StringUtils.trimToEmpty(
189 this.getExpression().getTranslatedExpression());
190
191 if (StringUtils.isNotEmpty(selectClauseTail)
192 && StringUtils.isNotEmpty(existingExpression)) {
193 this.selectClause.append(" ");
194 this.selectClause.append(selectClauseTail);
195 this.selectClause.append(" ");
196 }
197
198 this.getExpression().insertInTranslatedExpression(
199 0,
200 selectClause.toString());
201 }
202
203
204
205
206
207
208 public void handleSubSelect(String translation, Object node) {
209
210 APropertyCallExpression propertyCallExpression = (APropertyCallExpression)node;
211
212 String primaryExpression =
213 ConcreteSyntaxUtils.getPrimaryExpression(propertyCallExpression);
214
215
216
217 translation = this.replaceFragment(
218 translation,
219 TranslationUtils.trimToEmpty(primaryExpression),
220 0);
221
222 this.selectClause.append(" ");
223 this.selectClause.append(translation);
224 }
225
226 public void handleIsLike(String translation, Object node) {
227
228 APropertyCallExpression propertyCallExpression = (APropertyCallExpression)node;
229 List featureCalls = ConcreteSyntaxUtils.getFeatureCalls(propertyCallExpression);
230 AFeatureCall featureCall = (AFeatureCall)featureCalls.get(0);
231
232 List params =
233 ConcreteSyntaxUtils.getParameters(featureCall);
234
235 translation = this.replaceFragment(
236 translation,
237 TranslationUtils.deleteWhitespace(params.get(0)),
238 0);
239 translation = this.replaceFragment(
240 translation,
241 TranslationUtils.deleteWhitespace(params.get(1)),
242 1);
243
244 if (StringUtils.isNotEmpty(this.getExpression().getTranslatedExpression())) {
245 this.getExpression().appendSpaceToTranslatedExpression();
246 }
247 this.getExpression().appendToTranslatedExpression(translation);
248
249 }
250
251 public void handleSelect(String translation, Object node) {
252 this.selectClause.append(translation);
253 }
254
255 public void handleExists(String translation, Object node) {
256
257 APropertyCallExpression propertyCallExpression = (APropertyCallExpression)node;
258 List featureCalls = ConcreteSyntaxUtils.getFeatureCalls(propertyCallExpression);
259 AFeatureCall featureCall = (AFeatureCall)featureCalls.get(0);
260
261 String primaryExpression =
262 ConcreteSyntaxUtils.getPrimaryExpression(propertyCallExpression);
263
264 if (logger.isDebugEnabled()) {
265 logger.debug("primaryExpression --> '" + primaryExpression + "'");
266 }
267
268 String parameters =
269 StringUtils.deleteWhitespace(
270 ConcreteSyntaxUtils.getParametersAsString(featureCall));
271
272 translation = this.replaceFragment(
273 translation,
274 primaryExpression,
275 1);
276 translation = this.replaceFragment(
277 translation,
278 parameters,
279 0);
280
281 this.getExpression().appendSpaceToTranslatedExpression();
282 this.getExpression().appendToTranslatedExpression(translation);
283 }
284
285 public void handleIsEmpty(String translation, Object node) {
286
287 APropertyCallExpression propertyCallExpression = (APropertyCallExpression)node;
288
289 String primaryExpression =
290 ConcreteSyntaxUtils.getPrimaryExpression(propertyCallExpression);
291 if (logger.isDebugEnabled()) {
292 logger.debug("primaryExpression --> '" + primaryExpression + "'");
293 }
294
295 translation = this.replaceFragment(translation, primaryExpression, 0);
296
297 this.getExpression().appendSpaceToTranslatedExpression();
298 this.getExpression().appendToTranslatedExpression(translation);
299
300 }
301
302
303
304 public void handleLogicalExpression(String translation, Object node) {
305 this.getExpression().appendSpaceToTranslatedExpression();
306 this.getExpression().appendToTranslatedExpression(translation);
307 }
308
309
310
311 public void handleRelationalExpression(String translation, Object node) {
312
313 ARelationalExpressionTail relationalExpressionTail =
314 (ARelationalExpressionTail)node;
315
316 String[] leftAndRightExpressions =
317 ConcreteSyntaxUtils.getLeftAndRightExpressions(
318 (PRelationalExpression) relationalExpressionTail.parent());
319
320 String leftExpression =
321 StringUtils.deleteWhitespace(leftAndRightExpressions[0]);
322 String rightExpression =
323 StringUtils.deleteWhitespace(leftAndRightExpressions[1]);
324
325 translation = this.replaceFragment(translation, leftExpression, 0);
326 translation = this.replaceFragment(translation, rightExpression, 1);
327
328 this.getExpression().appendSpaceToTranslatedExpression();
329 this.getExpression().appendToTranslatedExpression(translation);
330
331 }
332
333 }