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