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: VariableElementSerializer.java 3622 2006-12-12 03:04:08Z lzheng $
023: */
024: package com.bostechcorp.cbesb.runtime.parser;
025:
026: import java.io.ByteArrayOutputStream;
027: import java.io.IOException;
028: import java.io.OutputStream;
029: import java.io.OutputStreamWriter;
030: import java.io.UnsupportedEncodingException;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.w3c.dom.Element;
035:
036: import com.bostechcorp.cbesb.common.mdl.IContentElement;
037: import com.bostechcorp.cbesb.common.mdl.IContentGroup;
038: import com.bostechcorp.cbesb.common.mdl.IContentNode;
039: import com.bostechcorp.cbesb.common.mdl.IElementDefinition;
040: import com.bostechcorp.cbesb.common.mdl.IVariableChildAttributes;
041: import com.bostechcorp.cbesb.common.mdl.IVariableFormatDefinition;
042:
043: /**
044: * The VariableElementSerializer class implements ElementSerializer. It is used
045: * to serialize Elements defined as variable format.
046: *
047: * Basic flow of the serialize method: 1. Verify that all child Elements of the
048: * DOM Element passed in match the child elements of the ElementDefinition
049: * passed in. 2. For each child Element do the following: a. Get the appropriate
050: * ElementSerializer for the child ElementDefinition. b. Call the serialize
051: * method of the child ElementSerializer, passing in a ByteArrayOutputStream
052: * instead of the real OutputStream. c. Verify that the data returned fits
053: * within the min and max length for the child definition. d. Escape any
054: * characters in the data that match the delimiter. e. Write the data to the
055: * OutputStream. f. Write the delimiter to the OutputStream.
056: *
057: */
058: public class VariableElementSerializer extends SerializerBase implements
059: IElementSerializer {
060:
061: protected transient Log log = LogFactory
062: .getLog(VariableElementSerializer.class);
063:
064: public void serialize(Element element,
065: IElementDefinition elementDefinition,
066: DataEscapingUtil dataEscapingUtil, OutputStream os)
067: throws ParserException {
068:
069: // Define all the special attribute for the variable serializer
070: IVariableFormatDefinition varDef = (IVariableFormatDefinition) elementDefinition
071: .getFormatDefinition();
072:
073: // Validate the element name, like orderrecord or manufacturer
074: validateElementName(element, elementDefinition);
075:
076: Element childElement = getFirstChildElement(element);
077: try {
078: OutputStreamWriter writer = new OutputStreamWriter(os,
079: "utf-8");
080: //Use separate logic to handle elements identified by position or tag.
081: if (varDef.getIDMethod() == IVariableFormatDefinition.ID_METHOD_POSITION) {
082: serializeVariableUsingPosition(childElement,
083: elementDefinition, varDef, dataEscapingUtil,
084: writer);
085: } else if (varDef.getIDMethod() == IVariableFormatDefinition.ID_METHOD_TAG) {
086: serializeVariableUsingTag(childElement,
087: elementDefinition, varDef, dataEscapingUtil,
088: writer);
089: }
090: writer.flush();
091: } catch (IOException e) {
092: throw new ParserException(
093: "IOException caught in VariableElementSerializer when serializing data to UTF-8 output stream.",
094: e);
095: // log.error("VariableElementSerializer caught exception:", e);
096: }
097: }
098:
099: private void serializeVariableUsingTag(Element childElement,
100: IElementDefinition elementDefinition,
101: IVariableFormatDefinition varDef,
102: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
103: throws ParserException, IOException {
104: log
105: .debug("VariableElementSerializer::serializeVariableUsingTag");
106:
107: //Add info to DataEscapingUtil
108: if (varDef.getResolvedEscapeChar() > 0) {
109: dataEscapingUtil.setEscapeChar(varDef
110: .getResolvedEscapeChar());
111: } else if (varDef.getResolvedQuoteChar() > 0) {
112: dataEscapingUtil
113: .setQuoteChar(varDef.getResolvedQuoteChar());
114: }
115: dataEscapingUtil.addDelimiter(varDef.getResolvedDelimiter());
116:
117: String tagDelimiter = varDef.getResolvedTagDelimiter();
118: if (tagDelimiter == null) {
119: tagDelimiter = "";
120: }
121:
122: IContentNode[] content = elementDefinition.getChildren();
123:
124: serializeTaggedContent(childElement, content,
125: elementDefinition, varDef, tagDelimiter,
126: dataEscapingUtil, writer);
127:
128: }
129:
130: private void serializeTaggedContent(Element childElement,
131: IContentNode[] content, IElementDefinition parentElemDef,
132: IVariableFormatDefinition varDef, String tagDelimiter,
133: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
134: throws ParserException, IOException {
135: for (int i = 0; i < content.length; i++) {
136: IContentNode contentNode = content[i];
137:
138: int minOccurs = contentNode.getMinOccurs();
139: int maxOccurs = contentNode.getMaxOccurs();
140: if (childElement != null
141: && validateElementName(childElement, contentNode,
142: parentElemDef)) {
143: if (contentNode instanceof IContentElement) {
144: serializeTagContentElement(childElement,
145: (IContentElement) contentNode,
146: parentElemDef, tagDelimiter,
147: dataEscapingUtil, writer);
148: } else if (contentNode instanceof IContentGroup) {
149: serializeTagContentGroup(childElement,
150: (IContentGroup) contentNode, parentElemDef,
151: varDef, tagDelimiter, dataEscapingUtil,
152: writer);
153: }
154:
155: //Check for repetitions
156: if (maxOccurs > 1 || maxOccurs == -1 /*unbounded*/) {
157: int count = 1;
158: Element nextSibling = getNextSiblingElement(childElement);
159: while (nextSibling != null
160: && validateElementName(nextSibling,
161: contentNode, parentElemDef)
162: && (maxOccurs == -1 || (maxOccurs != -1 && count < maxOccurs))) {
163: //Write a delimiter to separate the repetitions
164: writer.write(varDef.getResolvedDelimiter());
165: writer.flush();
166: if (contentNode instanceof IContentElement) {
167: serializeTagContentElement(nextSibling,
168: (IContentElement) contentNode,
169: parentElemDef, tagDelimiter,
170: dataEscapingUtil, writer);
171: } else if (contentNode instanceof IContentGroup) {
172: serializeTagContentGroup(nextSibling,
173: (IContentGroup) contentNode,
174: parentElemDef, varDef,
175: tagDelimiter, dataEscapingUtil,
176: writer);
177: }
178: childElement = nextSibling;
179: nextSibling = getNextSiblingElement(childElement);
180: count++;
181: }
182: }
183: childElement = getNextSiblingElement(childElement);
184: //If there are still siblings left, then write a delimiter
185: if (childElement != null) {
186: writer.write(varDef.getResolvedDelimiter());
187: writer.flush();
188: }
189: } else {
190: if (minOccurs > 0) {
191: //Required element is missing
192: // TODO Lu can we ignore this?
193: }
194: }
195:
196: }
197: }
198:
199: private void serializeTagContentElement(Element childElement,
200: IContentElement contentElem,
201: IElementDefinition parentElemDef, String tagDelimiter,
202: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
203: throws ParserException, IOException {
204: // IElementDefinition childElementDef = resolveChildElementDefinition(contentElem, parentElemDef.getMDLDocument());
205: IElementDefinition childElementDef = contentElem
206: .getResolvedElementDef();
207:
208: //Write out the tag
209: IVariableChildAttributes varChildAttr = (IVariableChildAttributes) contentElem
210: .getFormatChildAttributes();
211: String tag = varChildAttr.getTag();
212: writer.write(tag + tagDelimiter);
213: writer.flush();
214:
215: //Serialize the child
216: serializeChild(childElement, childElementDef, dataEscapingUtil,
217: writer);
218: }
219:
220: private void serializeTagContentGroup(Element groupElement,
221: IContentGroup groupDef, IElementDefinition parentElemDef,
222: IVariableFormatDefinition varDef, String tagDelimiter,
223: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
224: throws ParserException, IOException {
225: Element groupChild = getFirstChildElement(groupElement);
226: IContentNode[] content = groupDef.getChildren();
227: serializeTaggedContent(groupChild, content, parentElemDef,
228: varDef, tagDelimiter, dataEscapingUtil, writer);
229: }
230:
231: private void serializeVariableUsingPosition(Element childElement,
232: IElementDefinition elementDefinition,
233: IVariableFormatDefinition varDef,
234: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
235: throws ParserException, IOException {
236: log
237: .debug("VariableElementSerializer::serializeVariableUsingPosition");
238:
239: //Add info to DataEscapingUtil
240: if (varDef.getResolvedEscapeChar() > 0) {
241: dataEscapingUtil.setEscapeChar(varDef
242: .getResolvedEscapeChar());
243: } else if (varDef.getResolvedQuoteChar() > 0) {
244: dataEscapingUtil
245: .setQuoteChar(varDef.getResolvedQuoteChar());
246: }
247: dataEscapingUtil.addDelimiter(varDef.getResolvedDelimiter());
248: if (varDef.getResolvedRepeatDelimiter() != null
249: && varDef.getResolvedRepeatDelimiter().length() > 0) {
250: dataEscapingUtil.addDelimiter(varDef
251: .getResolvedRepeatDelimiter());
252: }
253:
254: for (int i = 0; i < elementDefinition.getChildCount(); i++) {
255: IContentNode contentNode = elementDefinition
256: .getChildAtIndex(i);
257:
258: if (!(contentNode instanceof IContentElement)) {
259: //Invalid MDL definition
260: //ID Method = position does not allow IContentGroup as a child.
261:
262: }
263: IContentElement contentElem = (IContentElement) contentNode;
264:
265: // IElementDefinition childElementDef = resolveChildElementDefinition(contentElem, elementDefinition.getMDLDocument());
266: IElementDefinition childElementDef = contentElem
267: .getResolvedElementDef();
268:
269: int minOccurs = contentElem.getMinOccurs();
270: int maxOccurs = contentElem.getMaxOccurs();
271:
272: if (childElement != null
273: && validateElementName(childElement, contentNode,
274: elementDefinition)) {
275:
276: //Serialize the child
277: serializeChild(childElement, childElementDef,
278: dataEscapingUtil, writer);
279:
280: //Check for repetitions
281: if (maxOccurs > 1 || maxOccurs == -1 /*unbounded*/) {
282: int count = 1;
283: Element nextSibling = getNextSiblingElement(childElement);
284: while (nextSibling != null
285: && validateElementName(nextSibling,
286: contentNode, elementDefinition)
287: && (maxOccurs == -1 || (maxOccurs != -1 && count < maxOccurs))) {
288: writer.write(varDef
289: .getResolvedRepeatDelimiter());
290: writer.flush();
291: serializeChild(nextSibling, childElementDef,
292: dataEscapingUtil, writer);
293: childElement = nextSibling;
294: nextSibling = getNextSiblingElement(childElement);
295: count++;
296: }
297: }
298: childElement = getNextSiblingElement(childElement);
299: } else {
300: if (minOccurs > 0) {
301: //Required element is missing
302: // TODO Lu can we ignore this?
303:
304: }
305: }
306:
307: //Write out delimiter for all elements except the last one
308: if (i < (elementDefinition.getChildCount() - 1)) {
309: writer.write(varDef.getResolvedDelimiter());
310: writer.flush();
311: }
312: }
313: }
314:
315: private void serializeChild(Element childElement,
316: IElementDefinition childDef,
317: DataEscapingUtil dataEscapingUtil, OutputStreamWriter writer)
318: throws ParserException, IOException {
319: ByteArrayOutputStream baos = new ByteArrayOutputStream();
320: IElementSerializer serializer = ElementSerializerFactory
321: .instance().getElementSerializer(childDef);
322: serializer.serialize(childElement, childDef, dataEscapingUtil,
323: baos);
324: String childData = null;
325: try {
326: childData = new String(baos.toByteArray(), "utf-8");
327: } catch (UnsupportedEncodingException e) {
328: throw new ParserException(
329: "IOExcept caught in VariableElementSerializer class when converting to UTF-8 String from element '"
330: + childDef.getNamespaceURI()
331: + ":"
332: + childDef.getName() + "'", e);
333: }
334:
335: writer.write(childData);
336: writer.flush();
337:
338: }
339:
340: }
|