View Javadoc

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