View Javadoc

1   package org.ocltf.translation.library;
2   
3   import java.io.BufferedReader;
4   import java.io.Reader;
5   import java.io.StringReader;
6   import java.io.StringWriter;
7   import java.lang.reflect.Method;
8   import java.net.URL;
9   import java.util.HashMap;
10  import java.util.Map;
11  
12  import org.apache.commons.digester.xmlrules.DigesterLoader;
13  import org.apache.commons.lang.StringUtils;
14  import org.apache.commons.lang.builder.ToStringBuilder;
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  import org.ocltf.common.ComponentContainer;
18  import org.ocltf.templateengine.TemplateEngine;
19  import org.ocltf.translation.Translator;
20  import org.ocltf.utils.ExceptionUtils;
21  import org.ocltf.utils.XmlResourceUtils;
22  
23  /***
24   * The LibraryTranslation object which stores
25   * 
26   * @author Chad Brandon
27   */
28  public class LibraryTranslation {
29  
30  	private static Log logger = LogFactory.getLog(LibraryTranslation.class);
31  
32  	private static final String CLASS_NAME = Translation.class.getName();
33  	private static final String TRANSLATION_RULES_XML = CLASS_NAME + "-Rules";
34  
35  	/***
36  	 * The parent library to which this LibraryTranslation belongs.
37  	 */
38  	private Library library;
39  
40  	private String name;
41  
42  	private String file;
43  
44  	/***
45  	 * The TemplateEngine implementation to use, if is set, then this one
46  	 * overrides the TemplateEngine definied on the library that this
47  	 * LibraryTranslation belongs to.
48  	 */
49  	private String templateEngineClass;
50  
51  	/***
52  	 * The Translator implementation to use. This is required.
53  	 */
54  	private String translatorClass;
55  
56  	/***
57  	 * After processing by the CartridgeTemplate engine, will contain the
58  	 * processed translation.
59  	 */
60  	private Translation translation;
61  
62  	/***
63  	 * @return String
64  	 */
65  	public String getName() {
66  		return name;
67  	}
68  
69  	/***
70       * Sets the name.
71       * 
72  	 * @param name
73  	 */
74  	public void setName(String name) {
75  		this.name = name;
76  	}
77  
78  	/***
79  	 * @return String
80  	 */
81  	public String getFile() {
82  		return file;
83  	}
84  
85  	/***
86  	 * @param file
87  	 */
88  	public void setFile(String file) {
89  		this.file = file;
90  	}
91  
92  	/***
93  	 * Returns the Library that this LibraryTranslation
94  	 * belongs too.
95  	 * 
96  	 * @return Library
97  	 */
98  	public Library getLibrary() {
99  		return library;
100 	}
101 
102 	/***
103 	 * @param library
104 	 */
105 	public void setLibrary(Library library) {
106 		this.library = library;
107 	}
108 
109 	/***
110 	 * Gets the TemplateEngine instance that will perform processing of the
111 	 * file.
112 	 * 
113 	 * @return TemplateEngine
114 	 */
115 	public TemplateEngine getTemplateEngine() {
116         return (TemplateEngine)ComponentContainer.instance().findComponent(
117             templateEngineClass, TemplateEngine.class);
118 	}
119 
120 	/***
121 	 * Sets the TemplateEngine class that will perform processing of the file.
122 	 * 
123 	 * @param templateEngineClass
124 	 */
125 	public void setTemplateEngine(String templateEngineClass) {
126 		this.templateEngineClass = templateEngineClass;
127 	}
128 
129 	/***
130 	 * Sets the Translator class that will perform the translation processing.
131 	 * 
132 	 * @param translatorClass
133 	 */
134 	public void setTranslator(String translatorClass) {
135         this.translatorClass = translatorClass;
136         ComponentContainer.instance().registerComponentType(translatorClass);
137 	}
138 
139 	/***
140 	 * Gets the Translator instance that will perform processing of the file.
141 	 * 
142 	 * @return Translator
143 	 */  
144 	public Translator getTranslator() {
145         String methodName = "getTranslator";
146         Translator translator = 
147             (Translator)ComponentContainer.instance().findComponent(
148                 this.translatorClass, Translator.class);
149         if (translator == null) {
150             throw new LibraryException(
151                     methodName
152                     + " - a translator implementation must be defined, "
153                     + " please check your translator library --> "
154                     + this.library.getResource());
155         }
156         return translator;
157 	}
158 
159 	/***
160 	 * Calls the handlerMethod from a translation fragment.  Each
161      * handle method must take a java.lang.String as the first argument 
162      * (the body of the fragment from the translation file) and a 
163      * java.lang.Object for the second argument (the node being parsed that
164      * we may need to retrieve any additional information from).
165 	 * 
166 	 * @param name the name of the fragment to retrieve.
167 	 * @param node the node Object which from the parsed expression.
168      * @param kind the kind of the translation fragment to handle.
169 	 */
170 	public void handleTranslationFragment(
171 		String name,
172         String kind,
173 		Object node) {
174 		String methodName = "handleTranslationFragment";
175         ExceptionUtils.checkNull(methodName, "node", node);
176 		if (this.translation != null && this.getTranslator() != null) {
177             
178             String translation = this.getTranslationFragment(name, kind);
179             
180             //only handle the fragment if we can find the fragment in the 
181             //translation file
182             if (StringUtils.isNotEmpty(translation)) {
183             
184     			String handlerMethod =
185     				this.translation.getFragment(name).getHandlerMethod();
186     			if (StringUtils.isNotEmpty(handlerMethod)) {
187                     
188                     Class[] argTypes = new Class[] {
189                         java.lang.String.class, 
190                         java.lang.Object.class
191                     };                
192                     
193     				try {
194         
195     					Method method =
196     						this.getTranslator().getClass().getMethod(
197     							handlerMethod,
198     							argTypes);               
199                         
200                         //add the translation as the first arg
201                         Object[] args = new Object[] {
202                             translation,
203                         	node
204                         };
205                         
206                         method.invoke(this.getTranslator(), args);
207     				} catch (NoSuchMethodException ex) {
208     					String errMsg =
209     						"the translator '"
210     							+ this.getTranslator().getClass()
211     							+ "' must implement the method '"
212     							+ handlerMethod
213     							+ "("
214     							+ StringUtils.join(argTypes, ",")
215     							+ ")'"
216     							+ " in order to handle processing of the fragment --> '"
217     							+ name
218     							+ "'";
219     					logger.error(errMsg);
220     				} catch (Exception ex) {
221     					String errMsg = "Error performing " + methodName;
222     					logger.error(errMsg, ex);
223     					throw new LibraryException(errMsg, ex);
224     				}
225     			}
226             }
227 		}
228 	}
229 
230 	/***
231 	 * Gets the current "translated" value of this fragmentName for resulting
232 	 * from the last processTranslation method
233 	 * 
234 	 * @param name the name of the fragment to retrieve.
235      * @param kind the kind or type of fragment to retrieve 
236      * (this is the based on the expression type: body, inv, post, pre, etc).
237 	 * 
238 	 * @return String the value of the translated fragment or null of one
239 	 *         wasn't found with the specified name.
240 	 */
241 	public String getTranslationFragment(String name, String kind) {
242 		String fragment = null;
243 		if (this.translation != null) {
244 			fragment = this.translation.getTranslated(name, kind);
245 		}
246 		return fragment;
247 	}
248 
249 	/***
250 	 * The processed translation template as a Reader.
251 	 * 
252 	 * @param translationInput
253 	 */
254 	protected void setTranslation(Reader translationInput) {
255 		String methodName = "setTranslation";
256 		ExceptionUtils.checkNull(
257 			methodName,
258 			"translationInput",
259 			translationInput);
260 		ClassLoader loader = Thread.currentThread().getContextClassLoader();
261 		URL rulesXml = XmlResourceUtils.getResource(TRANSLATION_RULES_XML);
262 		try {
263 			this.translation =
264 				(Translation) DigesterLoader.load(
265 					rulesXml,
266 					loader,
267 					translationInput);
268 			this.translation.setLibraryTranslation(this);
269 		} catch (Exception ex) {
270 			String errMsg = "Error performing " + methodName;
271 			logger.error(errMsg, ex);
272 			throw new LibraryException(errMsg, ex);
273 		}
274 	}
275 
276 	/***
277 	 * Processes the file belonging to this LibraryTranslation.
278 	 * 
279 	 * @param templateObjects -
280 	 *            any key/value pairs that should be passed to the
281 	 *            TemplateEngine while processing the translation file.
282 	 * 
283 	 * @return Translation - the Translation created from the processing the
284 	 *         translation file.
285 	 */
286 	public Translation processTranslation(Map templateObjects) {
287 		String methodName = "processTranslation";
288 		if (logger.isDebugEnabled()) {
289 			logger.debug(
290 				"processing translation file --> "
291 					+ this.getFile()
292 					+ " with templateObjects --> "
293 					+ templateObjects);
294 		}
295 
296 		if (templateObjects == null) {
297 			templateObjects = new HashMap();
298 		}
299 
300         templateObjects.putAll(this.getLibrary().getTemplateObjects());
301 
302 		try {
303 			TemplateEngine engine = this.getTemplateEngine();
304 
305 			StringWriter output = new StringWriter();
306 			engine.processTemplate(this.getFile(), templateObjects, output);
307 			String outputString = output.toString();
308 			BufferedReader input =
309 				new BufferedReader(new StringReader(outputString));
310 			if (logger.isDebugEnabled()) {
311 				logger.debug("processed output --> " + outputString);
312 			}
313 			//load Reader into the translation
314 			this.setTranslation(input);
315 		} catch (Exception ex) {
316 			String errMsg = "Error performing " + methodName;
317 			logger.error(errMsg, ex);
318 			throw new LibraryException(errMsg, ex);
319 		}
320 		return this.translation;
321 	}
322     
323     /***
324      * @see java.lang.Object#toString()
325      */
326 	public String toString() {
327 		return ToStringBuilder.reflectionToString(this);
328 	}
329 
330 }