package hu.sztaki.ilab.longneck.process.access; import hu.sztaki.ilab.longneck.Record; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import com.csvreader.CsvWriter; import hu.sztaki.ilab.longneck.Field; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Set; import org.apache.log4j.Logger; /** * CSV file target. * * @author LorĂ¡nd Bendig * */ public class CsvTarget implements Target { /** The runtime properties. */ protected Properties runtimeProperties; /** The name of the target from property. */ private String name; /** Name of the target file. */ private String path; /** default delimiter if not specified */ private Character delimiter = ';'; /** default empty value in the CSV content */ private String emptyValue = ""; /** Mappings between csv header names and field names in the form of csv_colname1=fieldname1 */ private String[] columns; /** Helper map. Key:csv_col_name, value:field_name */ private Map<String, String> headerFieldMapping = null; private CsvWriter writer; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDelimiter() { return delimiter.toString(); } public void setDelimiter(String delimiter) { if (delimiter.equals("")) { return; } if (delimiter.equals("\\t")) { this.delimiter = '\t'; } else { this.delimiter = delimiter.charAt(0); } } public String getEmptyValue() { return emptyValue; } public void setEmptyValue(String emptyValue) { this.emptyValue = emptyValue; } public String[] getColumns() { return columns; } public void setColumns(String[] columns) { this.columns = columns; } public Properties getRuntimeProperties() { return runtimeProperties; } public void setRuntimeProperties(Properties runtimeProperties) { this.runtimeProperties = runtimeProperties; } public CsvWriter getWriter() { return writer; } @Override public void truncate() { // NOPMD } @Override public void appendRecords(Collection<Record> records) { try { // If header field mapping is uninitialized get structure from first record if (headerFieldMapping == null && ! records.isEmpty()) { Iterator<Record> it = records.iterator(); initHeaderFieldMappingFromRecord(it.next()); } for (Record record : records) { Map<String, Field> fields = record.getFields(); for (String fname : headerFieldMapping.values()) { Field f = fields.get(fname); String val = (f == null) ? emptyValue : f.getValue(); writer.write(val); } writer.endRecord(); } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } @Override public void init() { if(path == null) { // Read target path from runtime properties path = runtimeProperties.getProperty(String.format("csvTarget.%1$s.path", name)); } try { // Initialize writer writer = new CsvWriter(new BufferedWriter(new FileWriter(path)), delimiter); if (columns == null) { Logger.getLogger(CsvTarget.class).info( "Output columns unspecified, using detection from first record."); } else { headerFieldMapping = new LinkedHashMap<String, String>(); String[] keyVal; for (String c : columns) { // Check, if the column is mapped if (c.contains("=")) { keyVal = c.split("="); } else { keyVal = new String[] { c, c }; } headerFieldMapping.put(trimColumnName(keyVal[0]), trimColumnName(keyVal[1])); } // Write header writer.writeRecord(headerFieldMapping.keySet().toArray(new String[0])); } } catch (IOException e) { throw new RuntimeException(e); } } private void initHeaderFieldMappingFromRecord(Record r) { headerFieldMapping = new LinkedHashMap<String, String>(); for (String fieldName : r.getFields().keySet()) { headerFieldMapping.put(fieldName, fieldName); } try { // Write header writer.writeRecord(headerFieldMapping.keySet().toArray(new String[0])); } catch (IOException e) { throw new RuntimeException(e); } } public Set<String> getFileds() { return headerFieldMapping == null?null:headerFieldMapping.keySet(); } @Override public void close() { try { if (writer != null) { writer.flush(); writer.close(); } } catch (IOException e) { throw new RuntimeException(e); } } private String trimColumnName(String s) { return StringUtils.removeEnd(s.trim(), ","); } }