/*
* 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.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.Schema;
import org.wso2.carbon.mediator.datamapper.engine.input.InputBuilder;
import org.wso2.carbon.mediator.datamapper.engine.input.builders.JSONBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.BOOLEAN_ELEMENT_TYPE;
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.NUMBER_ELEMENT_TYPE;
import static org.wso2.carbon.mediator.datamapper.engine.utils.DataMapperEngineConstants.PROPERTIES_KEY;
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;
/**
* This class is responsible for generating the JSON message for the given CSV message
*/
public class CSVInputReader implements InputReader {
private static final Log log = LogFactory.getLog(CSVInputReader.class);
/* JSON schema for input message */
private Map jsonSchema;
/* JSON schema of the input message */
private Schema inputSchema;
/* JSON message builder instance */
private JSONBuilder jsonBuilder;
/* Reference of the InputBuilder object to send the built JSON message */
private InputBuilder messageBuilder;
/**
* Constructor
*
* @throws IOException
*/
public CSVInputReader() throws IOException {
this.jsonBuilder = new JSONBuilder();
}
@Override
public void read(InputStream input, Schema inputSchema, InputBuilder messageBuilder) throws ReaderException {
this.inputSchema = inputSchema;
this.jsonSchema = inputSchema.getSchemaMap();
this.messageBuilder = messageBuilder;
OMXMLParserWrapper parserWrapper = OMXMLBuilderFactory.createOMBuilder(input);
OMElement root = parserWrapper.getDocumentElement();
String csvContent = getCSVContent(root);
try {
populateCSVContents(csvContent, jsonSchema);
} catch (IOException | SchemaException | JSException e) {
throw new ReaderException("Error while parsing CSV input stream. " + e.getMessage());
}
}
/**
* Populate CSV content to a JSON message
*
* @param csvContent CSV content extracted from the input message
* @param jsonSchemaMap respective JSON schema
* @throws IOException
* @throws ReaderException
* @throws SchemaException
* @throws JSException
*/
private void populateCSVContents(String csvContent, Map jsonSchemaMap)
throws IOException, ReaderException, SchemaException, JSException {
if (csvContent == null) {
throw new ReaderException(
"Request csv data not found. The csv records should contain in a <text></text> tag.");
}
String[] lines = csvContent.split("\\r?\\n");
Map<String, Object> fieldMap;
List<String> fieldNamesList;
if (lines.length > 0) {
/* Retrieve field names from the JSON schema */
fieldMap = (Map<String, Object>) ((Map<String, Object>) ((ArrayList) jsonSchemaMap.get(ITEMS_KEY)).get(0))
.get(PROPERTIES_KEY);
fieldNamesList = new ArrayList<>(fieldMap.keySet());
jsonBuilder.writeStartArray();
for (String line : lines) {
jsonBuilder.writeStartObject();
String[] items = line.split(",");
for (int i = 0; i < items.length; i++) {
writeFieldElement(fieldNamesList.get(i), items[i],
getElementTypeByName(fieldNamesList.get(i), fieldMap));
}
jsonBuilder.writeEndObject();
}
jsonBuilder.writeEndArray();
}
writeTerminateElement();
}
/**
* Extract CSV content from the input message
*
* @param element root element
* @return CSV content as text
*/
private String getCSVContent(OMElement element) {
if (element == null) {
log.warn("No CSV content found in the input file");
}
if (element.getLocalName().equals("text")) {
return element.getText();
}
Iterator<OMElement> it = element.getChildElements();
if (it.hasNext()) {
getCSVContent(it.next());
}
return null;
}
private String getElementTypeByName(String elementName, Map elementMap) {
String elementType = (String) ((Map) elementMap.get(elementName)).get(TYPE_KEY);
return elementType;
}
public Schema getInputSchema() {
return inputSchema;
}
private void writeFieldElement(String fieldName, String valueString, String fieldType)
throws IOException, JSException, SchemaException, ReaderException {
switch (fieldType) {
case STRING_ELEMENT_TYPE:
jsonBuilder.writeField(fieldName, valueString, fieldType);
break;
case BOOLEAN_ELEMENT_TYPE:
jsonBuilder.writeField(fieldName, Boolean.parseBoolean(valueString), fieldType);
break;
case NUMBER_ELEMENT_TYPE:
jsonBuilder.writeField(fieldName, Double.parseDouble(valueString), fieldType);
break;
case INTEGER_ELEMENT_TYPE:
jsonBuilder.writeField(fieldName, Integer.parseInt(valueString), fieldType);
break;
default:
jsonBuilder.writeField(fieldName, valueString, fieldType);
}
}
private void writeTerminateElement() throws IOException, JSException, SchemaException, ReaderException {
jsonBuilder.close();
String jsonBuiltMessage = jsonBuilder.getContent();
messageBuilder.notifyWithResult(jsonBuiltMessage);
}
}