001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: TransformerRuntime.java 12129 2008-02-28 16:09:20Z mpreston $
023: */
024: package com.bostechcorp.cbesb.runtime.transformer.engine;
025:
026: import java.io.ByteArrayInputStream;
027: import java.io.ByteArrayOutputStream;
028: import java.io.FileOutputStream;
029: import java.io.InputStreamReader;
030: import java.io.OutputStreamWriter;
031: import java.io.Reader;
032: import java.io.StringReader;
033: import java.io.StringWriter;
034: import java.io.UnsupportedEncodingException;
035: import java.io.Writer;
036: import java.util.HashMap;
037: import java.util.Vector;
038:
039: import javax.activation.DataHandler;
040: import javax.xml.parsers.DocumentBuilderFactory;
041: import javax.xml.parsers.ParserConfigurationException;
042: import javax.xml.transform.Source;
043: import javax.xml.transform.dom.DOMSource;
044:
045: import org.apache.commons.logging.Log;
046: import org.apache.commons.logging.LogFactory;
047: import org.w3c.dom.Document;
048: import org.w3c.dom.Node;
049:
050: import com.bostechcorp.cbesb.common.constant.MetadataConstants;
051: import com.bostechcorp.cbesb.common.i18n.Message;
052: import com.bostechcorp.cbesb.common.i18n.Messages;
053: import com.bostechcorp.cbesb.common.runtime.CbesbException;
054: import com.bostechcorp.cbesb.common.runtime.ConfigurationException;
055: import com.bostechcorp.cbesb.common.runtime.DataContentException;
056: import com.bostechcorp.cbesb.common.util.Dom;
057: import com.bostechcorp.cbesb.common.util.RuntimeClassLoader;
058: import com.bostechcorp.cbesb.runtime.ccsl.nmhandler.StringSource;
059: import com.bostechcorp.cbesb.runtime.parser.util.ParserUtil;
060: import com.bostechcorp.cbesb.runtime.parser.util.SerializerUtil;
061:
062: // The runtime environment for a translation
063: public class TransformerRuntime {
064: private static final Log log = LogFactory
065: .getLog(TransformerRuntime.class);
066: private String saName;
067: public ITransformer controller = null;
068: protected TransformerRuntimeFactory factory;
069:
070: //These must be in the same order as ITransformer
071: private static final String[] formatTypes = { "xsd", "mdl", "x12",
072: "hl7" };
073:
074: public TransformerRuntime(String translateControlClassName)
075: throws Exception {
076: this (null, translateControlClassName);
077: }
078:
079: public TransformerRuntime(String saName,
080: String translateControlClassName) throws CbesbException {
081: this (saName, translateControlClassName, null);
082: }
083:
084: public TransformerRuntime(String saName,
085: String translateControlClassName,
086: TransformerRuntimeFactory factory) throws CbesbException {
087: this .saName = saName;
088: this .factory = factory;
089: try {
090: // Class translateControl = Class.forName(translateControlClassName);
091: Class translateControl = Class.forName(
092: translateControlClassName, true, RuntimeClassLoader
093: .getClassLoader(saName, this ));
094: try {
095: controller = (ITransformer) translateControl
096: .newInstance();
097: if (saName != null)
098: controller.setServiceAssemblyName(saName);
099: } catch (ClassCastException e) {
100: // String message = "Class "+translateControlClassName+" does not extend TranslateControl";
101: String message = (new Message(
102: Messages.FAIL_TO_EXTEND_CLASS,
103: translateControlClassName)).getMessage();
104: // log.error(message);
105: throw new ConfigurationException(message, e);
106: } catch (Exception e) {
107: throw new ConfigurationException(
108: "Unable to load the transformer class for map - "
109: + e.getMessage(),
110: "Make sure the ESB project is built.", e);
111: }
112: } catch (ClassNotFoundException e) {
113: String message = "TranslateRuntime class "
114: + translateControlClassName + " was not found - "
115: + e.getMessage();
116: // log.error(message);
117: throw new ConfigurationException(message,
118: "Make sure the ESB project is built.", e);
119: }
120: }
121:
122: public void release() throws CbesbException {
123: if (factory != null) {
124: factory.releaseTransformerRuntime(saName, controller
125: .getClass().getCanonicalName(), this );
126: }
127: }
128:
129: public Vector<TransformerMessage> translate(
130: TransformerMessage transformerMsg) throws Exception {
131: return translate(transformerMsg, new HashMap());
132: }
133:
134: public void preProcessTransformerMessage(
135: TransformerMessage transformerMsg, HashMap metadataMap)
136: throws CbesbException {
137: Source src = transformerMsg.getSource();
138: if (src instanceof DOMSource) {
139: Node node = ((DOMSource) src).getNode();
140: if (node instanceof Document) {
141: transformerMsg.setDocument((Document) node);
142: } else {
143: transformerMsg.setDocument(node.getOwnerDocument());
144: }
145: } else if (src instanceof StringSource) {
146: transformerMsg.setDocument(preProcessInputStringSource(
147: (StringSource) src, metadataMap, controller
148: .getInFormatDef(), controller.getInRoot(),
149: controller.getInFormatType()));
150: } else {
151: throw new DataContentException(
152: "Unsupported source object type: " + src.toString());
153: }
154:
155: }
156:
157: /**
158: * It is for map tester to show the target tree
159: * @param transformerMsg
160: * @param metadataMap
161: * @throws CbesbException
162: */
163: public void processDomForTester(TransformerMessage transformerMsg,
164: HashMap metadataMap) throws CbesbException {
165: Source src = transformerMsg.getSource();
166: if (src instanceof DOMSource) {
167: Node node = ((DOMSource) src).getNode();
168: if (node instanceof Document) {
169: transformerMsg.setDocument((Document) node
170: .cloneNode(true));
171: } else {
172: transformerMsg.setDocument((Document) node
173: .getOwnerDocument().cloneNode(true));
174: }
175: } else if (src instanceof StringSource) {
176: Document doc = preProcessInputStringSource(
177: (StringSource) src, metadataMap, controller
178: .getOutFormatDef(),
179: controller.getOutRoot(), controller
180: .getOutFormatType());
181: transformerMsg.setDocument(doc);
182: } else {
183: throw new DataContentException(
184: "Unsupported source object type: " + src.toString());
185: }
186:
187: }
188:
189: public Vector<TransformerMessage> translate(
190: TransformerMessage transformerMsg, HashMap metadataMap)
191: throws CbesbException {
192:
193: if (transformerMsg.getDocument() == null) {
194: preProcessTransformerMessage(transformerMsg, metadataMap);
195: }
196: Vector<TransformerMessage> outputList = new Vector<TransformerMessage>();
197: try {
198: controller.doTransform(transformerMsg, outputList,
199: metadataMap);
200: } catch (TransformerException ex) {
201: throw ex;
202: } catch (Exception e) {
203: throw new DataContentException(
204: "Exception occurred executing transformation - "
205: + e.getMessage(), e);
206: }
207: postProcessOutput(outputList, metadataMap);
208: return outputList;
209: }
210:
211: // Only used by testing tool
212: public Vector<TransformerMessage> translate(Document source)
213: throws Exception {
214: TransformerMessage inTM = new TransformerMessage();
215: inTM.setSource(new DOMSource(source));
216: inTM.setMetadataMap(new HashMap<String, Object>());
217: inTM.setAttachmentMap(new HashMap<String, DataHandler>());
218: return this .translate(inTM, new HashMap());
219: }
220:
221: /**
222: *
223: * @param domOutputList
224: * @return
225: * @throws Exception
226: */
227: public void postProcessOutput(
228: Vector<TransformerMessage> outputList, HashMap metadataMap)
229: throws CbesbException {
230: for (int i = 0; i < outputList.size(); i++) {
231: TransformerMessage tm = outputList.elementAt(i);
232: Document doc = tm.getDocument();
233: Document newDoc = null;
234: newDoc = doc;
235:
236: this .postProcessAnonymousDom(newDoc);
237:
238: Object obj = postProcessOutputDom(newDoc, metadataMap);
239:
240: if (obj instanceof Document) {
241: tm.setSource(new DOMSource((Document) obj));
242: } else if (obj instanceof ByteArrayOutputStream) {
243: try {
244: tm.setSource(new StringSource(
245: ((ByteArrayOutputStream) obj)
246: .toString("utf-8")));
247: } catch (UnsupportedEncodingException e) {
248: throw new DataContentException(
249: CbesbException.ENCODING_ERR_UTF8_2_STR, e);
250: }
251: }
252: }
253: }
254:
255: public Document preProcessInputString(String s, HashMap metadataMap)
256: throws CbesbException {
257:
258: return this .preProcessInputString(s, metadataMap, controller
259: .getInFormatDef(), controller.getInRoot(), controller
260: .getInFormatType());
261: }
262:
263: /**
264: *
265: * @param source
266: * @param input
267: */
268: private Document preProcessInputString(String s,
269: HashMap metadataMap, String msgDefStr, String messageName,
270: int formatType) throws CbesbException {
271: Document input = null;
272: //String msgDefStr = controller.getInFormatDef();
273: // String messageName=controller.getInRoot();
274: if (formatType == ITransformer.FORMATTYPE_XSD) {
275: try {
276: input = Dom.getDomTree(new StringReader(s), null);
277: } catch (Exception e) {
278: throw new DataContentException(
279: "Exception parsing input data as XML - "
280: + e.getMessage(), e);
281: }
282: input.normalizeDocument();
283: } else {
284: ByteArrayInputStream bais;
285: try {
286: bais = new ByteArrayInputStream(s.getBytes("utf-8"));
287: } catch (UnsupportedEncodingException e) {
288: throw new DataContentException(
289: CbesbException.ENCODING_MSG_STR_2_utf8, e);
290: }
291: // ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
292: ParserUtil parser = new ParserUtil(this .saName);
293: processX12Separators(parser, metadataMap);
294: input = parser.parse(bais, getFormatString(formatType),
295: msgDefStr, messageName);
296: }
297: return input;
298: }
299:
300: public Document preProcessInputReader(Reader r, HashMap metadataMap)
301: throws Exception {
302: StringWriter w = new StringWriter();
303: char[] buf = new char[2048];
304: int l;
305: while ((l = r.read(buf)) > 0)
306: w.write(buf, 0, l);
307: return preProcessInputString(w.toString(), metadataMap,
308: controller.getInFormatDef(), controller.getInRoot(),
309: controller.getInFormatType());
310: }
311:
312: public Document preProcessInputStringSource(StringSource s,
313: HashMap metadataMap, String msgDefStr, String messageName,
314: int formatType) throws CbesbException {
315: return preProcessInputString(s.getText(), metadataMap,
316: msgDefStr, messageName, formatType);
317: }
318:
319: /**
320: * serialize a Document object to a File object
321: * @param outputDom
322: * @param outputFile
323: * @throws Exception
324: */
325: private Object postProcessOutputDom(Document outputDom,
326: HashMap metadataMap) throws CbesbException {
327:
328: if (controller.getOutFormatType() == ITransformer.FORMATTYPE_XSD) {
329: return (Object) outputDom;
330: } else {
331: ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
332: SerializerUtil serializer = new SerializerUtil();
333: processX12Separators(serializer, metadataMap);
334: serializer.serialize(outputStream, outputDom,
335: getFormatString(controller.getOutFormatType()),
336: controller.getOutFormatDef(), controller
337: .getOutRoot());
338: return (Object) outputStream;
339: }
340: }
341:
342: /**
343: * serialize a Document object to a File object
344: * @param outputDom
345: * @param outputFile
346: * @throws Exception
347: */
348: public void postProcessOutputToFile(TransformerMessage output,
349: String fileName) throws Exception {
350:
351: FileOutputStream os = new FileOutputStream(fileName);
352: String charset = (new InputStreamReader(
353: new ByteArrayInputStream(new byte[0]))).getEncoding();
354:
355: Source src = output.getSource();
356:
357: if (src instanceof DOMSource) {
358: Dom.writeDOMSource((DOMSource) src, os, charset);
359:
360: } else if (src instanceof StringSource) {
361: Writer out = new OutputStreamWriter(os, charset);
362: out.write(((StringSource) src).getText());
363: out.close();
364:
365: }
366:
367: }
368:
369: protected void processX12Separators(SerializerUtil serializer,
370: HashMap metadataMap) {
371: if (controller.getOutFormatType() == ITransformer.FORMATTYPE_X12) {
372: if (metadataMap
373: .containsKey(MetadataConstants.PARSER_X12_SEGMENTTERMINATOR)) {
374: String value = (String) metadataMap
375: .get(MetadataConstants.PARSER_X12_SEGMENTTERMINATOR);
376: if (value.length() > 0)
377: serializer.setX12SegmentTerminator(value.charAt(0));
378: }
379: if (metadataMap
380: .containsKey(MetadataConstants.PARSER_X12_FIELDSEPARATOR)) {
381: String value = (String) metadataMap
382: .get(MetadataConstants.PARSER_X12_FIELDSEPARATOR);
383: if (value.length() > 0)
384: serializer.setX12FieldSeparator(value.charAt(0));
385: }
386: if (metadataMap
387: .containsKey(MetadataConstants.PARSER_X12_COMPOSITESEPARATOR)) {
388: String value = (String) metadataMap
389: .get(MetadataConstants.PARSER_X12_COMPOSITESEPARATOR);
390: if (value.length() > 0)
391: serializer
392: .setX12CompositeSeparator(value.charAt(0));
393: }
394: }
395: }
396:
397: protected void processX12Separators(ParserUtil parser,
398: HashMap metadataMap) {
399: if (controller.getOutFormatType() == ITransformer.FORMATTYPE_X12) {
400: if (metadataMap
401: .containsKey(MetadataConstants.PARSER_X12_SEGMENTTERMINATOR)) {
402: String value = (String) metadataMap
403: .get(MetadataConstants.PARSER_X12_SEGMENTTERMINATOR);
404: if (value.length() > 0)
405: parser.setX12SegmentTerminator(value.charAt(0));
406: }
407: if (metadataMap
408: .containsKey(MetadataConstants.PARSER_X12_FIELDSEPARATOR)) {
409: String value = (String) metadataMap
410: .get(MetadataConstants.PARSER_X12_FIELDSEPARATOR);
411: if (value.length() > 0)
412: parser.setX12FieldSeparator(value.charAt(0));
413: }
414: if (metadataMap
415: .containsKey(MetadataConstants.PARSER_X12_COMPOSITESEPARATOR)) {
416: String value = (String) metadataMap
417: .get(MetadataConstants.PARSER_X12_COMPOSITESEPARATOR);
418: if (value.length() > 0)
419: parser.setX12CompositeSeparator(value.charAt(0));
420: }
421: }
422: }
423:
424: protected static String getFormatString(int formatType) {
425: return formatTypes[formatType];
426: }
427:
428: private void postProcessAnonymousDom(Document document) {
429: AnonymousNodeUtil.postProcessAnonymousNode(document
430: .getDocumentElement(), controller.getOutRootFormat());
431:
432: }
433:
434: }
|