/* * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.mediator.datamapper.engine.input.readers; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.om.OMXMLBuilderFactory; import org.apache.axiom.om.OMXMLParserWrapper; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.mediator.datamapper.engine.core.exceptions.InvalidPayloadException; import org.wso2.carbon.mediator.datamapper.engine.core.exceptions.JSException; import org.wso2.carbon.mediator.datamapper.engine.core.exceptions.ReaderException; import org.wso2.carbon.mediator.datamapper.engine.core.exceptions.SchemaException; import org.wso2.carbon.mediator.datamapper.engine.core.schemas.JacksonJSONSchema; import org.wso2.carbon.mediator.datamapper.engine.core.schemas.Schema; import org.wso2.carbon.mediator.datamapper.engine.input.InputBuilder; import org.wso2.carbon.mediator.datamapper.engine.input.builders.JSONBuilder; import org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.xml.namespace.QName; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.ARRAY_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.ATTRIBUTES_KEY; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.BOOLEAN_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.ENCODE_CHAR_HYPHEN; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.HYPHEN; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.INTEGER_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.ITEMS_KEY; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.NULL_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.NUMBER_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.OBJECT_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.PREFIX_LIST_SEPERATOR; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.PROPERTIES_KEY; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.SCHEMA_ATTRIBUTE_FIELD_PREFIX; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.SCHEMA_NAMESPACE_NAME_SEPARATOR; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.SCHEMA_XML_ELEMENT_TEXT_VALUE_FIELD; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.STRING_ELEMENT_TYPE; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.TYPE_KEY; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.VALUE_KEY; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.XMLNS; import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.XSI_NAMESPACE_URI; /** * This class is capable of parsing XML through AXIOMS for the InputStream and build the respective JSON message */ public class XMLInputReader implements InputReader { private static final Log log = LogFactory.getLog(XMLInputReader.class); /* Reference of the InputXMLMessageBuilder object to send the built JSON message */ private InputBuilder messageBuilder; /* JSON schema of the input message */ private Schema inputSchema; /* Name and NamespaceURI of the currently processing XML element */ private String localName; private String nameSpaceURI; /* JSON Builder to build the respective JSON message */ private JSONBuilder jsonBuilder; /* Iterator for the Attribute elements */ private Iterator<OMAttribute> it_attr; /* JSON schema for input message */ private Map jsonSchema; /** * Constructor * * @throws IOException */ public XMLInputReader() throws IOException { this.jsonBuilder = new JSONBuilder(); } /** * Read, parse the XML and notify with the output JSON message * * @param input XML message InputStream * @param inputSchema Schema of the input message * @param messageBuilder Reference of the InputXMLMessageBuilder * @throws ReaderException Exceptions in the parsing stage */ @Override public void read(InputStream input, Schema inputSchema, InputBuilder messageBuilder) throws ReaderException { this.messageBuilder = messageBuilder; this.inputSchema = inputSchema; OMXMLParserWrapper parserWrapper = OMXMLBuilderFactory.createOMBuilder(input); OMElement root = parserWrapper.getDocumentElement(); this.jsonSchema = getInputSchema().getSchemaMap(); try { xmlTraverse(root, null, jsonSchema); jsonBuilder.writeEndObject(); writeTerminateElement(); } catch (IOException | JSException | SchemaException | InvalidPayloadException e) { throw new ReaderException("Error while parsing XML input stream. " + e.getMessage()); } } /** * This method will perform a Depth First Search on the XML message and build the json message * * @param omElement initially the root element will be passed-in * @param prevElementName name of the previous element only if the previous element was an array, a null otherwise * @param jsonSchemaMap reduced json input schema map that is applicable to this level * @return the name of the previous element if the element was an array element, null otherwise * @throws IOException * @throws ReaderException * @throws SchemaException * @throws JSException * @throws InvalidPayloadException */ public String xmlTraverse(OMElement omElement, String prevElementName, Map jsonSchemaMap) throws IOException, ReaderException, SchemaException, JSException, InvalidPayloadException { /** isObject becomes true if the current element is an object, therefor object end element can be written at * the end */ boolean isObject = false; boolean isArrayElement = false; String prevElementNameSpaceLocalName = null; String elementType; Map nextJSONSchemaMap; /* iterator to hold the child elements of the passed OMElement */ Iterator<OMElement> it; /* Reading parameters of the currently processing OMElement */ localName = omElement.getLocalName(); nameSpaceURI = this.getNameSpaceURI(omElement); String nameSpaceLocalName = getNamespacesAndIdentifiersAddedFieldName(nameSpaceURI, localName, omElement, jsonSchemaMap); elementType = getElementType(jsonSchemaMap, nameSpaceLocalName); if (NULL_ELEMENT_TYPE.equals(elementType)) { /* Check whether the input payload has empty tags. */ log.warn("Element name not found : " + nameSpaceLocalName); } nextJSONSchemaMap = buildNextSchema(jsonSchemaMap, elementType, nameSpaceLocalName); if (nextJSONSchemaMap == null) { throw new ReaderException( "Input type is incorrect or Invalid element found in the message payload : " + nameSpaceLocalName); } /* if this is new object preceding an array, close the array before writing the new element */ if (prevElementName != null && !nameSpaceLocalName.equals(prevElementName)) { writeArrayEndElement(); prevElementName = null; } if (ARRAY_ELEMENT_TYPE.equals(elementType)) { if (prevElementName == null) { writeArrayStartElement(nameSpaceLocalName); } elementType = getArraySubElementType(jsonSchemaMap, nameSpaceLocalName); isArrayElement = true; } if (nameSpaceLocalName.equals(getInputSchema().getName())) { writeAnonymousObjectStartElement(); } else if (OBJECT_ELEMENT_TYPE.equals(elementType)) { isObject = true; if (isArrayElement) { writeAnonymousObjectStartElement(); elementType = getArrayObjectTextElementType(jsonSchemaMap, nameSpaceLocalName); } else { writeObjectStartElement(nameSpaceLocalName); elementType = getObjectTextElementType(jsonSchemaMap, nameSpaceLocalName); } } /* If an object/element(String/boolean/integer/number) property contains xis:nil=true need to avoid writing those fields */ if (!isXsiNil(omElement)) { /* If there is text in the OMElement */ if (DataMapperEngineConstants.STRING_ELEMENT_TYPE.equals(elementType) || DataMapperEngineConstants.BOOLEAN_ELEMENT_TYPE.equals(elementType) || DataMapperEngineConstants.INTEGER_ELEMENT_TYPE.equals(elementType) || DataMapperEngineConstants.NUMBER_ELEMENT_TYPE.equals(elementType)) { if (isObject) { // if it is a normal object or an array element object writeFieldElement(SCHEMA_XML_ELEMENT_TEXT_VALUE_FIELD, omElement.getText(), elementType); } else if (!isArrayElement) { // if it is a normal XML element (not a object or part of an array) writeFieldElement(nameSpaceLocalName, omElement.getText(), elementType); } else { // primitive array elements writePrimitiveElement(omElement.getText(), elementType); } } /* writing attributes to the JSON message */ it_attr = omElement.getAllAttributes(); if (it_attr.hasNext()) { writeAttributes(nextJSONSchemaMap); } it = omElement.getChildElements(); /* Recursively call all the children */ while (it.hasNext()) { prevElementNameSpaceLocalName = xmlTraverse(it.next(), prevElementNameSpaceLocalName, nextJSONSchemaMap); } } /* Closing the opened JSON objects and arrays */ if (prevElementNameSpaceLocalName != null) { writeArrayEndElement(); } if (isObject) { writeObjectEndElement(); } if (isArrayElement) { return nameSpaceLocalName; } return null; } /** * This method is used to get the namespace URI of an XML element (OMElement) * * @param omElement * @return Namespace URI of the given OMElement, if there is no Namespace return an empty String */ private String getNameSpaceURI(OMElement omElement) { String nameSpaceURI = ""; if (omElement.getNamespace() != null) { nameSpaceURI = omElement.getNamespace().getNamespaceURI(); } return nameSpaceURI; } /** * This method is used to get the namespace URI of an XML attribute (OMAttribute) * * @param omAttribute * @return Namespace URI of the given OMAttribute, if there is no Namespace return an empty String */ private String getNameSpaceURI(OMAttribute omAttribute) { String nameSpaceURI = ""; if (omAttribute.getNamespace() != null) { nameSpaceURI = omAttribute.getNamespace().getNamespaceURI(); } return nameSpaceURI; } /** * This method writes attribute elements into the JSON input message * * @param jsonSchemaMap current level JSON Schema * @throws JSException * @throws SchemaException * @throws ReaderException * @throws IOException * @throws InvalidPayloadException */ private void writeAttributes(Map jsonSchemaMap) throws JSException, SchemaException, ReaderException, IOException, InvalidPayloadException { /* currently processing attribute element and its parameters*/ String attributeType; String attributeFieldName; String attributeLocalName; String attributeNSURI; String attributeQName; OMAttribute omAttribute; /** Writing next attributes to the JSON message */ while (it_attr.hasNext()) { omAttribute = it_attr.next(); /* skip if the attribute name contains "XMLNS" */ attributeLocalName = omAttribute.getLocalName(); if (attributeLocalName.contains(XMLNS)) continue; attributeNSURI = this.getNameSpaceURI(omAttribute); attributeFieldName = getAttributeFieldName(attributeLocalName, attributeNSURI, jsonSchemaMap); attributeQName = getAttributeQName(omAttribute.getNamespace(), attributeLocalName, jsonSchemaMap); /* get the type of the attribute element */ attributeType = getElementType(jsonSchemaMap, attributeQName); if (NULL_ELEMENT_TYPE.equals(attributeType)) { /* Check whether the input payload has empty tags. */ log.warn("Attribute name not found : " + attributeQName); } /* write the attribute to the JSON message */ writeFieldElement(attributeFieldName, omAttribute.getAttributeValue(), attributeType); } } /** * Get the element type by referring to the input schema * * @param jsonSchemaMap Current level of the schema map * @param elementName Name of the OMElement * @return Type of the element * @throws SchemaException */ private String getElementType(Map jsonSchemaMap, String elementName) throws SchemaException { String elementType = NULL_ELEMENT_TYPE; if (elementName.equals(getInputSchema().getName())) { elementType = (String) jsonSchemaMap.get(TYPE_KEY); } else if (jsonSchemaMap.containsKey(elementName)) { elementType = (String) ((Map<String, Object>) jsonSchemaMap.get(elementName)).get(TYPE_KEY); } return elementType; } /** * Get the next schema level to pass to the next element search * * @param jsonSchemaMap Current level of the schema map * @param elementType Type of the parent element * @param elementName Name of the parent element * @return Next level schema map * @throws SchemaException */ private Map buildNextSchema(Map jsonSchemaMap, String elementType, String elementName) throws SchemaException { Map nextSchema = null; if (elementName.equals(getInputSchema().getName())) { nextSchema = (Map<String, Object>) jsonSchemaMap.get(PROPERTIES_KEY); } else if (jsonSchemaMap.containsKey(elementName)) { if (ARRAY_ELEMENT_TYPE.equals(elementType)) { nextSchema = ((JacksonJSONSchema) inputSchema) .getSchemaItems((Map<String, Object>) jsonSchemaMap.get(elementName)); nextSchema = getSchemaProperties(nextSchema); } else { nextSchema = getSchemaProperties((Map<String, Object>) jsonSchemaMap.get(elementName)); } } return nextSchema; } /** * Go to the next level of the schema * * @param schema Current level of the schema * @return next level schema */ private Map<String, Object> getSchemaProperties(Map<String, Object> schema) { Map<String, Object> nextSchema = new HashMap<>(); if (schema.containsKey(PROPERTIES_KEY)) { nextSchema.putAll((Map<? extends String, Object>) schema.get(PROPERTIES_KEY)); } if (schema.containsKey(ATTRIBUTES_KEY)) { nextSchema.putAll((Map<? extends String, Object>) schema.get(ATTRIBUTES_KEY)); } return nextSchema; } /** * Get the array elements sub-type. It can either be an object or primitive type * * @param jsonSchemaMap Current level json schema * @param elementName Name of the element * @return sub-type of the array element */ private String getArraySubElementType(Map jsonSchemaMap, String elementName) { ArrayList itemsList = (ArrayList) ((Map<String, Object>) jsonSchemaMap.get(elementName)).get(ITEMS_KEY); String output = (String) ((Map) itemsList.get(0)).get(TYPE_KEY); return output; } /** * Get the primitive type of an element * Main type :array * Sub-type :object * * @param jsonSchemaMap Current level json schema * @param elementName Name of the element * @return Primitive type or NULL_TYPE if there is not primitive text in the object */ private String getArrayObjectTextElementType(Map jsonSchemaMap, String elementName) { ArrayList itemsList = (ArrayList) ((Map<String, Object>) jsonSchemaMap.get(elementName)).get(ITEMS_KEY); Map itemsMap = (Map) itemsList.get(0); return getTextElementType(itemsMap); } /** * Get the primitive type of an element * Main type :object * * @param jsonSchemaMap Current level json schema * @param elementName Name of the element * @return Primitive type or NULL_TYPE if there is not primitive text in the object */ private String getObjectTextElementType(Map jsonSchemaMap, String elementName) { Map objectsMap = (Map<String, Object>) jsonSchemaMap.get(elementName); return getTextElementType(objectsMap); } /** * Get primitive type (used for getArrayObjectTextElementType, getObjectTextElementType methods) * * @param objectsMap * @return primitive type or NULL_TYPE of there is no primitive text */ private String getTextElementType(Map objectsMap) { if (!objectsMap.containsKey(VALUE_KEY)) { return NULL_ELEMENT_TYPE; } String output = (String) ((Map<String, Object>) (objectsMap.get(VALUE_KEY))).get(TYPE_KEY); return output; } /** * Elements Local name modifier methods */ private String getAttributeFieldName(String qName, String uri, Map jsonSchemaMap) throws SchemaException { String[] qNameOriginalArray = qName.split(SCHEMA_NAMESPACE_NAME_SEPARATOR); qName = getNamespacesAndIdentifiersAddedFieldName(uri, qNameOriginalArray[qNameOriginalArray.length - 1], null, jsonSchemaMap); String[] qNameArray = qName.split(SCHEMA_NAMESPACE_NAME_SEPARATOR); if (qNameArray.length > 1) { return SCHEMA_ATTRIBUTE_FIELD_PREFIX + qNameArray[0] + SCHEMA_NAMESPACE_NAME_SEPARATOR + qNameArray[qNameArray.length - 1]; } else { return SCHEMA_ATTRIBUTE_FIELD_PREFIX + qName; } } private String getNamespacesAndIdentifiersAddedFieldName(String uri, String localName, OMElement omElement, Map jsonSchemaMap) throws SchemaException { String modifiedLocalName = null; String[] xsiNamespacePrefix; String namespaceURI; OMNamespace xsiNamespace = null; String prefix = resolveUriToPrefix(uri, localName, jsonSchemaMap); if (StringUtils.isNotEmpty(prefix)) { modifiedLocalName = prefix + SCHEMA_NAMESPACE_NAME_SEPARATOR + localName; } else { modifiedLocalName = localName; } String prefixInMap = inputSchema.getNamespaceMap().get(XSI_NAMESPACE_URI); if (prefixInMap != null && omElement != null) { String xsiType = omElement.getAttributeValue(new QName(XSI_NAMESPACE_URI, "type")); if (xsiType != null) { xsiNamespacePrefix = xsiType.split(":", 2); xsiNamespace = omElement.findNamespaceURI(xsiNamespacePrefix[0]); if (xsiNamespace != null) { namespaceURI = xsiNamespace.getNamespaceURI(); if (prefixInMap.contains(PREFIX_LIST_SEPERATOR)) { String[] prefixArr = prefixInMap.split(PREFIX_LIST_SEPERATOR); String tempModifiedLocalName; /** * At this point xsi type may have data-type which it's prefix represent multiple namespace uri as shown in the below sample xml <root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd2="http://www.w3.org/2001/XMLSchema"> <testNS:element1 xsi:type="xsd2:string">car</testNS:element1> <testNS:element2 xsi:type="xsd:string">car</testNS:element2> </root> **/ if (!getInputSchema().getPrefixForNamespace(namespaceURI).contains(PREFIX_LIST_SEPERATOR)) { for (String targetPrefix : prefixArr) { tempModifiedLocalName = modifiedLocalName + "," + targetPrefix + ":type=" + getInputSchema().getPrefixForNamespace(namespaceURI) + ":" + xsiNamespacePrefix[1]; if (jsonSchemaMap.containsKey(tempModifiedLocalName)) { modifiedLocalName = tempModifiedLocalName; break; } } } else { //there are multiple prefixes for xsi type String[] xsdTypePrefixArray = getInputSchema(). getPrefixForNamespace(namespaceURI).split(PREFIX_LIST_SEPERATOR); for (String targetPrefix : prefixArr) { for (String xsdTypePrefix : xsdTypePrefixArray) { tempModifiedLocalName = modifiedLocalName + "," + targetPrefix + ":type=" + xsdTypePrefix + ":" + xsiNamespacePrefix[1]; if (jsonSchemaMap.containsKey(tempModifiedLocalName)) { modifiedLocalName = tempModifiedLocalName; break; } } } } } else { modifiedLocalName = modifiedLocalName + "," + prefixInMap + ":type=" + getInputSchema() .getPrefixForNamespace(namespaceURI) + ":" + xsiNamespacePrefix[1]; } } else { modifiedLocalName = modifiedLocalName + "," + prefixInMap + ":type=" + xsiType; } } } return modifiedLocalName; } /** * Function to resolve relevant prefix for the provided namespace URI. If multiple prefixes exists, this will * resolve it for the current XML traversal level * @return resolved namespace prefix */ private String resolveUriToPrefix (String uri, String localName, Map jsonSchemaMap) throws SchemaException { String prefix = getInputSchema().getPrefixForNamespace(uri); if (StringUtils.isNotEmpty(prefix) && prefix.contains(",")) { //multiple prefixes exists for this namespace URI. hence adding all prefixes that related to same // namespace separating by commas //adding comma separated prefix string is looks UGLY :-/, BUT can't help .... !, trying to do with //minimum impact existing mechanism if (jsonSchemaMap != null) { String[] prefixArray = prefix.split(PREFIX_LIST_SEPERATOR); prefix = null; String tempNamespaceLocalName; for (String tempPrefix : prefixArray) { tempNamespaceLocalName = tempPrefix + SCHEMA_NAMESPACE_NAME_SEPARATOR + localName; if (tempNamespaceLocalName.equals(getInputSchema().getName()) || jsonSchemaMap.containsKey(tempNamespaceLocalName)) { //found matching namespace prefix for this level for target URI prefix = tempPrefix; break; } } if (prefix == null) { //Still didn't find the matching namespace prefix. May be due to xsi:type attribute exists in the //input schema and it appended to the schema map key. eg: test2:name,xsi:type=xsd:string for // <test2:name test1:nameType="productID" xsi:type="xsd:string" // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">car</test2:name> Iterator<String> iterator = jsonSchemaMap.keySet().iterator(); while (iterator.hasNext() && prefix == null) { String elementName = iterator.next(); for (String tempPrefix : prefixArray) { tempNamespaceLocalName = tempPrefix + SCHEMA_NAMESPACE_NAME_SEPARATOR + localName + ","; if (elementName.startsWith(tempNamespaceLocalName)) { prefix = tempPrefix; break; } } } } } else { prefix = null; log.warn("Multiple prefixes exists for element local name: " + localName + " with URI: " + uri + ". But jsonSchemaMap not provided"); } } return prefix; } private boolean isXsiNil(OMElement omElement) { String prefixInMap = inputSchema.getNamespaceMap().get(XSI_NAMESPACE_URI); if (prefixInMap != null && omElement != null) { if (prefixInMap.contains(PREFIX_LIST_SEPERATOR)) { //if multiple prefixes for xsi namespace String[] prefixArray = prefixInMap.split(PREFIX_LIST_SEPERATOR); for (String prefix : prefixArray) { String xsiNilValue = omElement.getAttributeValue(new QName(XSI_NAMESPACE_URI, "nil", prefix)); if (xsiNilValue != null && "true".equalsIgnoreCase(xsiNilValue)) { return true; } } return false; } String xsiNilValue = omElement.getAttributeValue(new QName(XSI_NAMESPACE_URI, "nil", prefixInMap)); if (xsiNilValue != null && "true".equalsIgnoreCase(xsiNilValue)) { return true; } } return false; } public String getAttributeQName(OMNamespace omNamespace, String localName) { if (omNamespace != null) { return omNamespace.getPrefix() + ":" + localName; } else { return localName; } } /** * This function will resolve prefix for given URI depending on the provided traversal level given by jsonSchemaMap * @param omNamespace * @param localName * @param jsonSchemaMap * @return * @throws SchemaException */ public String getAttributeQName(OMNamespace omNamespace, String localName, Map jsonSchemaMap) throws SchemaException { if (omNamespace != null) { String prefix = resolveUriToPrefix(omNamespace.getNamespaceURI(), localName, jsonSchemaMap); return prefix + ":" + localName; } else { return localName; } } public Schema getInputSchema() { return inputSchema; } /** * JSON message building methods */ private void writeFieldElement(String fieldName, String valueString, String fieldType) throws IOException, JSException, SchemaException, ReaderException { switch (fieldType) { case STRING_ELEMENT_TYPE: jsonBuilder.writeField(getModifiedFieldName(fieldName), valueString, fieldType); break; case BOOLEAN_ELEMENT_TYPE: jsonBuilder.writeField(getModifiedFieldName(fieldName), Boolean.parseBoolean(valueString), fieldType); break; case NUMBER_ELEMENT_TYPE: jsonBuilder.writeField(getModifiedFieldName(fieldName), Double.parseDouble(valueString), fieldType); break; case INTEGER_ELEMENT_TYPE: jsonBuilder.writeField(getModifiedFieldName(fieldName), Integer.parseInt(valueString), fieldType); break; default: jsonBuilder.writeField(getModifiedFieldName(fieldName), valueString, fieldType); } } private void writePrimitiveElement(String valueString, String fieldType) throws IOException, JSException, SchemaException, ReaderException { switch (fieldType) { case STRING_ELEMENT_TYPE: jsonBuilder.writePrimitive(valueString, fieldType); break; case BOOLEAN_ELEMENT_TYPE: jsonBuilder.writePrimitive(Boolean.parseBoolean(valueString), fieldType); break; case NUMBER_ELEMENT_TYPE: jsonBuilder.writePrimitive(Double.parseDouble(valueString), fieldType); break; case INTEGER_ELEMENT_TYPE: jsonBuilder.writePrimitive(Integer.parseInt(valueString), fieldType); break; default: jsonBuilder.writePrimitive(valueString, fieldType); } } private void writeObjectStartElement(String fieldName) throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.writeObjectFieldStart(getModifiedFieldName(fieldName)); } private void writeObjectEndElement() throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.writeEndObject(); } private void writeArrayStartElement(String fieldName) throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.writeArrayFieldStart(getModifiedFieldName(fieldName)); } private void writeArrayEndElement() throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.writeEndArray(); } private void writeTerminateElement() throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.close(); String jsonBuiltMessage = jsonBuilder.getContent(); messageBuilder.notifyWithResult(jsonBuiltMessage); } private void writeAnonymousObjectStartElement() throws IOException, JSException, SchemaException, ReaderException { jsonBuilder.writeStartObject(); } private String getModifiedFieldName(String fieldName) { return fieldName.replace(SCHEMA_NAMESPACE_NAME_SEPARATOR, "_") .replace(",", DataMapperEngineConstants.NAME_SEPERATOR).replace("=", "_").replace(HYPHEN, ENCODE_CHAR_HYPHEN); } }