View Javadoc
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 }