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
181
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
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
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 }