001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.dataformat.csv;
018
019 import java.io.InputStream;
020 import java.io.InputStreamReader;
021 import java.io.OutputStream;
022 import java.io.OutputStreamWriter;
023 import java.util.ArrayList;
024 import java.util.Arrays;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.Set;
028
029 import org.apache.camel.Exchange;
030 import org.apache.camel.spi.DataFormat;
031 import org.apache.camel.util.ExchangeHelper;
032 import org.apache.camel.util.ObjectHelper;
033 import org.apache.commons.csv.CSVParser;
034 import org.apache.commons.csv.CSVStrategy;
035 import org.apache.commons.csv.writer.CSVConfig;
036 import org.apache.commons.csv.writer.CSVField;
037 import org.apache.commons.csv.writer.CSVWriter;
038
039 /**
040 * CSV Data format.
041 * <p/>
042 * By default, columns are autogenerated in the resulting CSV. Subsequent
043 * messages use the previously created columns with new fields being added at
044 * the end of the line. Thus, field order is the same from message to message.
045 * Autogeneration can be disabled. In this case, only the fields defined in
046 * csvConfig are written on the output.
047 *
048 * @version $Revision: 3239 $
049 */
050 public class CsvDataFormat implements DataFormat {
051 private CSVStrategy strategy = CSVStrategy.DEFAULT_STRATEGY;
052 private CSVConfig config = new CSVConfig();
053 private boolean autogenColumns = true;
054
055 public void marshal(Exchange exchange, Object object, OutputStream outputStream) throws Exception {
056 ObjectHelper.notNull(config, "config");
057
058 Map map = ExchangeHelper.convertToMandatoryType(exchange, Map.class, object);
059 OutputStreamWriter out = new OutputStreamWriter(outputStream);
060 try {
061 if (autogenColumns) {
062 // no specific config has been set so lets add fields
063 Set set = map.keySet();
064 updateFieldsInConfig(set, exchange);
065 }
066 CSVWriter writer = new CSVWriter(config);
067 writer.setWriter(out);
068 writer.writeRecord(map);
069 } finally {
070 out.close();
071 }
072 }
073
074 public Object unmarshal(Exchange exchange, InputStream inputStream) throws Exception {
075 InputStreamReader in = new InputStreamReader(inputStream);
076 try {
077 CSVParser parser = new CSVParser(in, getStrategy());
078 List<List<String>> list = new ArrayList<List<String>>();
079 while (true) {
080 String[] strings = parser.getLine();
081 if (strings == null) {
082 break;
083 }
084 List<String> line = Arrays.asList(strings);
085 list.add(line);
086 }
087 if (list.size() == 1) {
088 return list.get(0);
089 } else {
090 return list;
091 }
092 } finally {
093 in.close();
094 }
095 }
096
097 public void setConfig(CSVConfig config) {
098 this.config = config;
099 }
100
101 public CSVStrategy getStrategy() {
102 return strategy;
103 }
104
105 public void setStrategy(CSVStrategy strategy) {
106 this.strategy = strategy;
107 }
108
109 public boolean isAutogenColumns() {
110 return autogenColumns;
111 }
112
113 /**
114 * Auto generate columns.
115 *
116 * @param autogenColumns set to false to disallow column autogeneration (default true)
117 */
118 public void setAutogenColumns(boolean autogenColumns) {
119 this.autogenColumns = autogenColumns;
120 }
121
122 protected CSVConfig createConfig() {
123 return new CSVConfig();
124 }
125
126 private synchronized void updateFieldsInConfig(Set set, Exchange exchange) {
127 for (Object value : set) {
128 if (value != null) {
129 String text = exchange.getContext().getTypeConverter().convertTo(String.class, value);
130 // do not add field twice
131 if (config.getField(text) == null) {
132 CSVField field = new CSVField(text);
133 config.addField(field);
134 }
135 }
136 }
137 }
138
139 }