/*
* Copyright (c) 2014 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.io.csv.writer.internal;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.xml.namespace.QName;
import org.apache.commons.io.FileUtils;
import au.com.bytecode.opencsv.CSVWriter;
import com.google.common.io.Files;
import eu.esdihumboldt.hale.common.core.io.IOProviderConfigurationException;
import eu.esdihumboldt.hale.common.core.io.ProgressIndicator;
import eu.esdihumboldt.hale.common.core.io.report.IOReport;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl;
import eu.esdihumboldt.hale.common.instance.model.Instance;
import eu.esdihumboldt.hale.common.instance.model.InstanceCollection;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
import eu.esdihumboldt.hale.io.csv.InstanceTableIOConstants;
import eu.esdihumboldt.hale.io.csv.reader.internal.CSVUtil;
import eu.esdihumboldt.hale.io.csv.writer.AbstractTableInstanceWriter;
/**
* Provider for exporting instances as csv files
*
* @author Patrick Lieb
*/
public class CSVInstanceWriter extends AbstractTableInstanceWriter {
private char sep;
private char quote;
private char esc;
/**
* @see eu.esdihumboldt.hale.common.core.io.IOProvider#isCancelable()
*/
@Override
public boolean isCancelable() {
return false;
}
/**
* @see eu.esdihumboldt.hale.common.core.io.impl.AbstractIOProvider#execute(eu.esdihumboldt.hale.common.core.io.ProgressIndicator,
* eu.esdihumboldt.hale.common.core.io.report.IOReporter)
*/
@Override
protected IOReport execute(ProgressIndicator progress, IOReporter reporter)
throws IOProviderConfigurationException, IOException {
boolean solveNestedProperties = getParameter(
InstanceTableIOConstants.SOLVE_NESTED_PROPERTIES).as(Boolean.class, false);
// XXX what does "solve nested properties" mean?
// get separation, quote and escape sign
sep = CSVUtil.getSep(this);
quote = CSVUtil.getQuote(this);
esc = CSVUtil.getEscape(this);
List<String> headerRow = new ArrayList<String>();
// get the parameter to get the type definition
String exportType = getParameter(InstanceTableIOConstants.EXPORT_TYPE).as(String.class);
QName selectedTypeName = null;
if (exportType != null && !exportType.equals("") && !exportType.equals(" ")) {
selectedTypeName = QName.valueOf(exportType);
}
// get all instances of the selected Type
InstanceCollection instances = getInstanceCollection(selectedTypeName);
Iterator<Instance> instanceIterator = instances.iterator();
Instance instance = null;
try {
instance = instanceIterator.next();
} catch (NoSuchElementException e) {
reporter.error(new IOMessageImpl("There are no instances for the selected type.", e));
return reporter;
}
// get definition of current instance (only this properties with this
// definition type will be written to csv file)
TypeDefinition definition = instance.getDefinition();
// first csv file doesn't have a header row, so it' necessary to write
// it to a temp directory
File tempDir = Files.createTempDir();
File tempFile = new File(tempDir, "tempInstances.csv");
// write instances to csv file (without header)
CSVWriter writer = new CSVWriter(new OutputStreamWriter(new FileOutputStream(tempFile)),
sep, quote, esc);
writeLine(solveNestedProperties, headerRow, instance, writer);
while (instanceIterator.hasNext()) {
Instance nextInst = instanceIterator.next();
if (nextInst.getDefinition().equals(definition)) {
writeLine(solveNestedProperties, headerRow, nextInst, writer);
}
}
writer.close();
// header is only finished if all properties have been processed
// insert header to temp file and write it to output
insertHeader(tempFile, getTarget().getOutput(), headerRow);
FileUtils.deleteDirectory(tempDir);
reporter.setSuccess(true);
return reporter;
}
@Override
public boolean isPassthrough() {
return true;
}
// write current instance to csv file
private void writeLine(boolean solveNestedProperties, List<String> headerRow,
Instance instance, CSVWriter writer) {
List<String> line = new ArrayList<String>();
Map<String, Object> row = super.getPropertyMap(instance, headerRow, solveNestedProperties);
for (String key : headerRow) {
Object entry = row.get(key);
line.add(getValueOfProperty(entry));
}
writer.writeNext(line.toArray(new String[line.size()]));
}
/**
* @see eu.esdihumboldt.hale.common.core.io.impl.AbstractIOProvider#getDefaultTypeName()
*/
@Override
protected String getDefaultTypeName() {
return "csv file";
}
// insert header into csv file (at beginning of file)
private void insertHeader(File source, OutputStream dest, List<String> header)
throws IOException {
String line = "";
FileInputStream fis = new FileInputStream(source);
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
PrintWriter out = new PrintWriter(dest);
for (String entry : header) {
line += entry;
line += sep;
}
// remove last separator
line = line.substring(0, line.lastIndexOf(sep));
out.println(line);
String thisLine = "";
while ((thisLine = in.readLine()) != null) {
out.println(thisLine);
}
out.flush();
out.close();
in.close();
source.delete();
}
private String getValueOfProperty(Object property) {
if (property == null) {
return "";
}
else {
if (property instanceof Instance) {
Object instValue = ((Instance) property).getValue();
if (instValue != null) {
return (instValue.toString());
}
}
return property.toString();
}
}
}