/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.camel.component.flatpack;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import net.sf.flatpack.DataSet;
import net.sf.flatpack.DefaultParserFactory;
import net.sf.flatpack.Parser;
import net.sf.flatpack.ParserFactory;
import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultPollingEndpoint;
import org.apache.camel.processor.loadbalancer.LoadBalancer;
import org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.util.ExchangeHelper;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.ResourceHelper;
/**
* The flatpack component supports fixed width and delimited file parsing via the FlatPack library.
*/
@UriEndpoint(firstVersion = "1.4.0", scheme = "flatpack", title = "Flatpack", syntax = "flatpack:type:resourceUri", consumerClass = FlatpackConsumer.class, label = "transformation")
public class FlatpackEndpoint extends DefaultPollingEndpoint {
private LoadBalancer loadBalancer = new RoundRobinLoadBalancer();
private ParserFactory parserFactory = DefaultParserFactory.getInstance();
@UriPath @Metadata(required = "false", defaultValue = "delim")
private FlatpackType type;
@UriPath @Metadata(required = "true")
private String resourceUri;
@UriParam(defaultValue = "true")
private boolean splitRows = true;
@UriParam
private boolean allowShortLines;
@UriParam
private boolean ignoreExtraColumns;
// delimited
@UriParam(defaultValue = ",")
private char delimiter = ',';
@UriParam
private char textQualifier = '"';
@UriParam(defaultValue = "true")
private boolean ignoreFirstRecord = true;
public FlatpackEndpoint() {
}
public FlatpackEndpoint(String endpointUri, Component component, String resourceUri) {
super(endpointUri, component);
this.resourceUri = resourceUri;
}
public boolean isSingleton() {
return true;
}
public Producer createProducer() throws Exception {
return new FlatpackProducer(this);
}
public Consumer createConsumer(Processor processor) throws Exception {
return new FlatpackConsumer(this, processor, loadBalancer);
}
public void processDataSet(Exchange originalExchange, DataSet dataSet, int counter) throws Exception {
Exchange exchange = ExchangeHelper.createCorrelatedCopy(originalExchange, false);
Message in = exchange.getIn();
in.setBody(dataSet);
in.setHeader("CamelFlatpackCounter", counter);
loadBalancer.process(exchange);
}
public Parser createParser(Exchange exchange) throws Exception {
Reader bodyReader = exchange.getIn().getMandatoryBody(Reader.class);
try {
if (FlatpackType.fixed == type) {
return createFixedParser(resourceUri, bodyReader);
} else {
return createDelimitedParser(exchange);
}
} catch (Exception e) {
// must close reader in case of some exception
IOHelper.close(bodyReader);
throw e;
}
}
protected Parser createFixedParser(String resourceUri, Reader bodyReader) throws IOException {
InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), resourceUri);
InputStreamReader reader = new InputStreamReader(is);
Parser parser = getParserFactory().newFixedLengthParser(reader, bodyReader);
if (isAllowShortLines()) {
parser.setHandlingShortLines(true);
parser.setIgnoreParseWarnings(true);
}
if (isIgnoreExtraColumns()) {
parser.setIgnoreExtraColumns(true);
parser.setIgnoreParseWarnings(true);
}
return parser;
}
public Parser createDelimitedParser(Exchange exchange) throws InvalidPayloadException, IOException {
Reader bodyReader = exchange.getIn().getMandatoryBody(Reader.class);
Parser parser;
if (ObjectHelper.isEmpty(getResourceUri())) {
parser = getParserFactory().newDelimitedParser(bodyReader, delimiter, textQualifier);
} else {
InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), resourceUri);
InputStreamReader reader = new InputStreamReader(is, IOHelper.getCharsetName(exchange));
parser = getParserFactory().newDelimitedParser(reader, bodyReader, delimiter, textQualifier, ignoreFirstRecord);
}
if (isAllowShortLines()) {
parser.setHandlingShortLines(true);
parser.setIgnoreParseWarnings(true);
}
if (isIgnoreExtraColumns()) {
parser.setIgnoreExtraColumns(true);
parser.setIgnoreParseWarnings(true);
}
return parser;
}
// Properties
//-------------------------------------------------------------------------
public String getResourceUri() {
return resourceUri;
}
public ParserFactory getParserFactory() {
return parserFactory;
}
public void setParserFactory(ParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
public LoadBalancer getLoadBalancer() {
return loadBalancer;
}
public void setLoadBalancer(LoadBalancer loadBalancer) {
this.loadBalancer = loadBalancer;
}
public boolean isSplitRows() {
return splitRows;
}
/**
* Sets the Component to send each row as a separate exchange once parsed
*/
public void setSplitRows(boolean splitRows) {
this.splitRows = splitRows;
}
public boolean isAllowShortLines() {
return this.allowShortLines;
}
/**
* Allows for lines to be shorter than expected and ignores the extra characters
*/
public void setAllowShortLines(boolean allowShortLines) {
this.allowShortLines = allowShortLines;
}
/**
* Allows for lines to be longer than expected and ignores the extra characters
*/
public void setIgnoreExtraColumns(boolean ignoreExtraColumns) {
this.ignoreExtraColumns = ignoreExtraColumns;
}
public boolean isIgnoreExtraColumns() {
return ignoreExtraColumns;
}
public FlatpackType getType() {
return type;
}
/**
* Whether to use fixed or delimiter
*/
public void setType(FlatpackType type) {
this.type = type;
}
/**
* URL for loading the flatpack mapping file from classpath or file system
*/
public void setResourceUri(String resourceUri) {
this.resourceUri = resourceUri;
}
public char getDelimiter() {
return delimiter;
}
/**
* The default character delimiter for delimited files.
*/
public void setDelimiter(char delimiter) {
this.delimiter = delimiter;
}
public char getTextQualifier() {
return textQualifier;
}
/**
* The text qualifier for delimited files.
*/
public void setTextQualifier(char textQualifier) {
this.textQualifier = textQualifier;
}
public boolean isIgnoreFirstRecord() {
return ignoreFirstRecord;
}
/**
* Whether the first line is ignored for delimited files (for the column headers).
*/
public void setIgnoreFirstRecord(boolean ignoreFirstRecord) {
this.ignoreFirstRecord = ignoreFirstRecord;
}
}