package org.openlca.io.xls;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import org.openlca.core.database.EntityCache;
import org.openlca.core.math.DataStructures;
import org.openlca.core.matrix.ExchangeMatrix;
import org.openlca.core.matrix.FlowIndex;
import org.openlca.core.matrix.Inventory;
import org.openlca.core.matrix.LongPair;
import org.openlca.core.matrix.TechIndex;
import org.openlca.core.model.descriptors.FlowDescriptor;
import org.openlca.io.CategoryPair;
import org.openlca.io.DisplayValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Writes a product system as matrices into CSV files.
*/
public class CsvMatrixExport implements Runnable {
private Logger log = LoggerFactory.getLogger(getClass());
private EntityCache cache;
private CsvMatrixExportData data;
private String separator;
private String point;
private HashMap<Long, String> categoryCache = new HashMap<>();
public CsvMatrixExport(CsvMatrixExportData data) {
this.data = data;
cache = data.getEntityCache();
separator = data.getColumnSeperator();
point = data.getDecimalSeparator();
}
@Override
public void run() {
log.trace("Run matrix export");
if (data == null || !data.valid()) {
log.error("Invalid export data {}", data);
return;
}
log.trace("Build inventory matrix");
Inventory inventory = DataStructures.createInventory(
data.getProductSystem(), data.getMatrixCache());
log.trace("Write technology matrix");
writeTechFile(inventory);
log.trace("Write intervention matrix");
writeEnviFile(inventory);
log.trace("Export done");
}
private void writeTechFile(Inventory inventory) {
try (FileWriter writer = new FileWriter(data.getTechnologyFile());
BufferedWriter buffer = new BufferedWriter(writer)) {
writeTechMatrix(inventory, buffer);
} catch (Exception e) {
log.error("Failed to write technology matrix", e);
}
}
private void writeTechMatrix(Inventory inventory, BufferedWriter buffer)
throws Exception {
ExchangeMatrix techMatrix = inventory.technologyMatrix;
TechIndex techIndex = inventory.productIndex;
int size = techIndex.size();
for (int row = 0; row < size; row++) {
LongPair product = techIndex.getProviderAt(row);
FlowDescriptor flow = getFlow(product.getSecond());
writeName(flow, buffer);
sep(buffer);
writeCategory(flow, buffer);
sep(buffer);
for (int col = 0; col < size; col++) {
double val = techMatrix.getValue(row, col);
writeValue(val, buffer);
sep(buffer, col, size);
}
buffer.newLine();
}
}
private void writeEnviFile(Inventory inventory) {
try (FileWriter writer = new FileWriter(data.getInterventionFile());
BufferedWriter buffer = new BufferedWriter(writer)) {
writeEnviMatrix(inventory, buffer);
} catch (Exception e) {
log.error("Failed to write intervention matrix", e);
}
}
private void writeEnviMatrix(Inventory inventory, BufferedWriter buffer)
throws Exception {
TechIndex techIndex = inventory.productIndex;
FlowIndex flowIndex = inventory.flowIndex;
int rows = flowIndex.size();
int columns = techIndex.size();
writeEnviMatrixHeader(buffer, techIndex);
ExchangeMatrix matrix = inventory.interventionMatrix;
for (int row = 0; row < rows; row++) {
FlowDescriptor flow = getFlow(flowIndex.getFlowAt(row));
writeName(flow, buffer);
sep(buffer);
writeCategory(flow, buffer);
sep(buffer);
for (int col = 0; col < columns; col++) {
double val = matrix.getValue(row, col);
writeValue(val, buffer);
sep(buffer, col, columns);
}
buffer.newLine();
}
}
private void writeEnviMatrixHeader(BufferedWriter buffer,
TechIndex techIndex) throws Exception, IOException {
sep(buffer);
sep(buffer);
int columns = techIndex.size();
for (int col = 0; col < columns; col++) {
LongPair product = techIndex.getProviderAt(col);
FlowDescriptor flow = getFlow(product.getSecond());
writeName(flow, buffer);
sep(buffer, col, columns);
}
buffer.newLine();
sep(buffer);
sep(buffer);
for (int col = 0; col < columns; col++) {
LongPair product = techIndex.getProviderAt(col);
FlowDescriptor flow = getFlow(product.getSecond());
writeCategory(flow, buffer);
sep(buffer, col, columns);
}
buffer.newLine();
}
private FlowDescriptor getFlow(long id) {
return cache.get(FlowDescriptor.class, id);
}
private void writeName(FlowDescriptor flow, Writer buffer) throws Exception {
if (flow == null)
return;
String name = flow.getName();
try {
String unit = DisplayValues.referenceUnit(flow, cache);
name = name.concat(" [").concat(unit).concat("]");
quote(name, buffer);
} catch (Exception e) {
log.error("Failed to load ref-unit", e);
return;
}
}
private void writeValue(double d, Writer buffer) throws Exception {
String number = Double.toString(d);
if (!point.equals("."))
number = number.replace(".", point);
buffer.write(number);
}
private void quote(String val, Writer buffer) throws Exception {
buffer.write('"');
buffer.write(val);
buffer.write('"');
}
private void sep(Writer buffer) throws Exception {
buffer.append(separator);
}
private void sep(Writer buffer, int position, int dimension)
throws Exception {
if (position < dimension - 1)
sep(buffer);
}
private void writeCategory(FlowDescriptor flow, Writer buffer)
throws Exception {
if (flow == null || flow.getCategory() == null)
return;
String catPath = categoryCache.get(flow.getCategory());
if (catPath == null) {
catPath = CategoryPair.create(flow, cache).toPath();
categoryCache.put(flow.getCategory(), catPath);
}
quote(catPath, buffer);
}
}