01: package org.andromda.translation.ocl.query;
02:
03: import org.andromda.core.translation.TranslationUtils;
04: import org.apache.commons.lang.StringUtils;
05:
06: import java.util.HashMap;
07: import java.util.Map;
08:
09: /**
10: * Performs translation to the following: <ul> <li>EJB-QL</li> </ul>
11: *
12: * @author Chad Brandon
13: */
14: public class EjbQLTranslator extends QueryTranslator {
15: /**
16: * Used to replace the 'counter' reference in the EJB-QL template
17: */
18: private static final String ARG_COUNTER = "counter";
19:
20: /**
21: * Keeps track of an incrementing argument number.
22: */
23: private short argCounter;
24:
25: /**
26: * Holds the arguments which have previously been used during translation. The key is the argument name BEFORE
27: * translation, and the value is the argument name AFTER translation.
28: */
29: private Map usedArguments = new HashMap();
30:
31: /**
32: * Called by super class to reset any objects.
33: */
34: public void preProcess() {
35: super .preProcess();
36: this .usedArguments.clear();
37: this .resetArgCounter();
38: }
39:
40: /**
41: * Resets the argCounter variable to its beginning value.
42: */
43: private void resetArgCounter() {
44: this .argCounter = 1;
45: }
46:
47: /**
48: * Returns a String representing an incrementing number. It increments and returns the next value each time this
49: * method is called.
50: *
51: * @return String the counter represented by a String.
52: */
53: protected String getCounter() {
54: return String.valueOf(argCounter++);
55: }
56:
57: /**
58: * Checks to see if the replacement is an argument and if so replaces the {index} in the fragment with the
59: * 'argument' fragment from the template. Otherwise replaces the {index} with the passed in replacement value.
60: *
61: * @param fragment
62: * @param replacement
63: * @param index
64: * @return String the fragment with any replacements.
65: */
66: protected String replaceFragment(String fragment,
67: String replacement, int index) {
68: if (this .isOperationArgument(replacement)) {
69: // get the used argument and if it exists, use that for the
70: // replacement, otherwise use a new one.
71: String usedArgument = (String) this .usedArguments
72: .get(replacement);
73: if (StringUtils.isEmpty(usedArgument)) {
74: String argument = this
75: .getTranslationFragment("argument");
76: argument = this .replaceCounterPattern(argument);
77: this .usedArguments.put(replacement, argument);
78: replacement = argument;
79: } else {
80: replacement = usedArgument;
81: }
82: }
83: return super .replaceFragment(fragment, replacement, index);
84: }
85:
86: /**
87: * Handles the replacemenht of the references to 'counter' with the incrementing counter (currently just used for
88: * EJB-QL translation) --> may want to find a cleaner way to do this.
89: */
90: protected String replaceCounterPattern(String fragment) {
91: if (TranslationUtils.containsPattern(fragment,
92: EjbQLTranslator.ARG_COUNTER)) {
93: fragment = TranslationUtils.replacePattern(fragment,
94: EjbQLTranslator.ARG_COUNTER, this.getCounter());
95: }
96: return fragment;
97: }
98: }
|