package org.openlca.io.csv.output;
import java.util.Map;
import org.openlca.core.database.IDatabase;
import org.openlca.core.model.Actor;
import org.openlca.core.model.Category;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.Flow;
import org.openlca.core.model.FlowType;
import org.openlca.core.model.PedigreeMatrix;
import org.openlca.core.model.PedigreeMatrixRow;
import org.openlca.core.model.Process;
import org.openlca.core.model.Source;
import org.openlca.core.model.Uncertainty;
import org.openlca.core.model.Unit;
import org.openlca.core.model.UnitGroup;
import org.openlca.io.UnitMapping;
import org.openlca.io.maps.MapType;
import org.openlca.io.maps.MappingBuilder;
import org.openlca.io.maps.content.CSVElementaryCategoryContent;
import org.openlca.io.maps.content.SPElementaryFlowContent;
import org.openlca.io.maps.content.CSVGeographyContent;
import org.openlca.io.maps.content.CSVQuantityContent;
import org.openlca.io.maps.content.CSVUnitContent;
import org.openlca.simapro.csv.model.IDistribution;
import org.openlca.simapro.csv.model.SPLogNormalDistribution;
import org.openlca.simapro.csv.model.SPNormalDistribution;
import org.openlca.simapro.csv.model.SPPedigreeMatrix;
import org.openlca.simapro.csv.model.SPProcess;
import org.openlca.simapro.csv.model.SPProcessDocumentation;
import org.openlca.simapro.csv.model.SPReferenceData;
import org.openlca.simapro.csv.model.SPTriangleDistribution;
import org.openlca.simapro.csv.model.SPUniformDistribution;
import org.openlca.simapro.csv.model.enums.ElementaryFlowType;
import org.openlca.simapro.csv.model.enums.Geography;
import org.openlca.simapro.csv.model.enums.ProcessCategory;
import org.openlca.simapro.csv.model.enums.ProcessType;
import org.openlca.simapro.csv.model.enums.ProductType;
import org.openlca.simapro.csv.model.process.ElementaryExchangeRow;
import org.openlca.simapro.csv.model.process.LiteratureReferenceRow;
import org.openlca.simapro.csv.model.process.ProductExchangeRow;
import org.openlca.simapro.csv.model.process.ProductOutputRow;
import org.openlca.simapro.csv.model.refdata.ElementaryFlowRow;
import org.openlca.simapro.csv.model.refdata.LiteratureReferenceBlock;
import org.openlca.simapro.csv.model.refdata.Quantity;
import org.openlca.simapro.csv.model.refdata.UnitRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class ProcessConverter {
private Logger log = LoggerFactory.getLogger(getClass());
private SPProcess spProcess;
private Process process;
private SPReferenceData referenceData;
private Map<String, CSVGeographyContent> geoMap;
private Map<String, SPElementaryFlowContent> elemMap;
private Map<String, CSVElementaryCategoryContent> categoryMap;
private Map<String, CSVUnitContent> unitMap;
private Map<String, CSVQuantityContent> quantityMap;
private UnitMapping unitMapping;
ProcessConverter(IDatabase database, SPReferenceData referenceData) {
this.referenceData = referenceData;
unitMapping = UnitMapping.createDefault(database);
MappingBuilder mappingBuilder = new MappingBuilder(database);
geoMap = mappingBuilder.buildExportMapping(CSVGeographyContent.class,
MapType.CSV_GEOGRAPHY);
elemMap = mappingBuilder.buildExportMapping(
SPElementaryFlowContent.class, MapType.CSV_ELEMENTARY_FLOW);
categoryMap = mappingBuilder.buildExportMapping(
CSVElementaryCategoryContent.class,
MapType.CSV_ELEMENTARY_CATEGORY);
unitMap = mappingBuilder.buildExportMapping(CSVUnitContent.class,
MapType.CSV_UNIT);
quantityMap = mappingBuilder.buildExportMapping(
CSVQuantityContent.class, MapType.CSV_QUANTITY);
}
SPProcess convert(Process process) {
this.process = process;
spProcess = new SPProcess(referenceProduct());
generalInformations();
elementaryExchanges();
productExchanges();
literatureReferences();
return spProcess;
}
private void generalInformations() {
SPProcessDocumentation documentation = new SPProcessDocumentation(
process.getName(), ProcessCategory.MATERIAL, getType());
spProcess.setDocumentation(documentation);
documentation.setComment(process.getDescription());
documentation.setCreationDate(process.getDocumentation()
.getCreationDate().toString());
documentation.setInfrastructureProcess(process
.isInfrastructureProcess());
geography(documentation);
System.out.println(documentation.getGenerator());
if (documentation.getGenerator() != null)
documentation.setGenerator(documentation.getGenerator());
}
private String getActorAsString(Actor actor) {
StringBuilder builder = new StringBuilder();
builder.append("Name: " + actor.getName());
if (actor.getAddress() != null)
builder.append(" Address:" + actor.getAddress());
if (actor.getCity() != null)
builder.append(" City:" + actor.getCity());
if (actor.getCountry() != null)
builder.append(" e-mail: " + actor.getEmail());
if (actor.getTelefax() != null)
builder.append(" Telefax: " + actor.getTelefax());
if (actor.getTelephone() != null)
builder.append(" Telephone: " + actor.getTelephone());
if (actor.getWebsite() != null)
builder.append(" Website: " + actor.getWebsite());
if (actor.getZipCode() != null)
builder.append(" Zip code: " + actor.getZipCode());
return builder.toString();
}
private ProcessType getType() {
if (process.getProcessType() == org.openlca.core.model.ProcessType.UNIT_PROCESS)
return ProcessType.UNIT_PROCESS;
return ProcessType.SYSTEM;
}
private void geography(SPProcessDocumentation documentation) {
CSVGeographyContent content = geoMap.get(process.getLocation()
.getRefId());
if (content != null)
documentation.setGeography(content.getGeography());
else
documentation.setGeography(Geography.UNKNOWN);
}
private void literatureReferences() {
for (Source source : process.getDocumentation().getSources()) {
String category = null;
if (source.getCategory() != null)
category = source.getCategory().getName();
else
category = "Others";
LiteratureReferenceBlock reference = new LiteratureReferenceBlock(
source.getName(), source.getTextReference(), category);
if (!"".equals(source.getDescription()))
reference.setContent(source.getDescription());
referenceData.add(source.getName(), reference);
spProcess.getDocumentation().getLiteratureReferenceEntries()
.add(new LiteratureReferenceRow(reference));
}
}
private ProductOutputRow referenceProduct() {
Exchange exchange = process.getQuantitativeReference();
ProductOutputRow product = new ProductOutputRow();
product.setName(exchange.getFlow().getName());
product.setUnit(map(exchange.getUnit()).getName());
product.setAmount(String.valueOf(exchange.getAmountValue()));
// TODO create a category tree
// product.setCategory(process.getCategory().getName());
product.setCategory("Others");
// TODO: check
return product;
}
private void productExchanges() {
for (Exchange exchange : process.getExchanges()) {
if (exchange.getFlow().getFlowType() != FlowType.PRODUCT_FLOW
|| exchange.getFlow().getFlowType() != FlowType.WASTE_FLOW)
continue;
Flow olcaFlow = exchange.getFlow();
ProductExchangeRow productFlow = new ProductExchangeRow();
productFlow.setName(olcaFlow.getName());
productFlow.setUnit(map(exchange.getUnit()).getName());
productFlow.setAmount(String.valueOf(exchange.getAmountValue()));
productFlow.setType(getProductFlowType(exchange));
spProcess.getProductFlows().add(productFlow);
}
}
private ProductType getProductFlowType(Exchange exchange) {
if (exchange.isInput())
return ProductType.MATERIAL_INPUT;
else
return ProductType.AVOIDED_PRODUCT;
}
private void elementaryExchanges() {
for (Exchange exchange : process.getExchanges()) {
if (exchange.getFlow().getFlowType() != FlowType.ELEMENTARY_FLOW)
continue;
String casNumber = null;
ElementaryExchangeRow flow = null;
SPElementaryFlowContent content = elemMap.get(exchange.getFlow()
.getRefId());
if (content != null) {
flow = content.createFlow();
referenceData.add(content.getUnit());
referenceData.add(new Quantity(content.getUnit()
.getQuantity(), new UnitRow(content.getUnit()
.getReferenceUnit())));
casNumber = content.getCasNumber();
} else {
flow = createElementaryFlow(exchange);
casNumber = exchange.getFlow().getCasNumber();
}
if (exchange.isInput()) {
flow.setType(ElementaryFlowType.RESOURCE);
} else {
if (flow.getType() != null) {
// TODO: throw right exception
}
// TODO: on this point the conversion will failed.
}
flow.setAmount(String.valueOf(exchange.getAmountValue()));
flow.setUncertainty(convertDistribition(exchange.getUncertainty(),
exchange.getPedigreeUncertainty()));
ElementaryFlowRow substance = new ElementaryFlowRow(flow.getName(),
flow.getUnit());
substance.setFlowType(flow.getType());
substance.setCASNumber(casNumber);
referenceData.add(substance);
spProcess.getElementaryFlows().add(flow);
}
}
private ElementaryExchangeRow createElementaryFlow(Exchange exchange) {
Flow olcaFlow = exchange.getFlow();
ElementaryExchangeRow flow = new ElementaryExchangeRow();
flow.setName(olcaFlow.getName());
flow.setUnit(map(exchange.getUnit()).getName());
flow.setAmount(String.valueOf(exchange.getAmountValue()));
CSVElementaryCategoryContent categoryContent = categoryMap.get(olcaFlow
.getCategory().getRefId());
if (categoryContent != null) {
flow.setType(categoryContent.getType());
flow.setSubCompartment(categoryContent.getSubCompartment());
} else {
StringBuilder builder = new StringBuilder();
builder.append("Can not find category mapping for flow '");
builder.append(olcaFlow.getName());
builder.append("' in category '");
Category current = olcaFlow.getCategory();
String categoryTree = null;
while (current != null) {
if (categoryTree != null)
categoryTree = "/" + categoryTree;
categoryTree = current.getName() + categoryTree;
current = current.getCategory();
}
builder.append(categoryTree);
log.error(builder.toString());
}
return flow;
}
private UnitRow map(Unit unit) {
CSVUnitContent content = unitMap.get(unit.getRefId());
UnitRow spUnit = null;
if (content == null) {
spUnit = new UnitRow(unit.getName());
spUnit.setConversionFactor(unit.getConversionFactor());
UnitGroup unitGroup = unitMapping.getUnitGroup(unit.getName());
spUnit.setQuantity(map(unitGroup).getName());
spUnit.setReferenceUnit(unitGroup.getReferenceUnit().getName());
} else {
spUnit = content.createUnit();
}
referenceData.add(spUnit);
referenceData.add(new Quantity(spUnit.getQuantity(), new UnitRow(
spUnit.getReferenceUnit())));
return spUnit;
}
private Quantity map(UnitGroup unitGroup) {
CSVQuantityContent content = quantityMap.get(unitGroup.getRefId());
if (content == null)
return new Quantity(unitGroup.getName(), new UnitRow(unitGroup
.getReferenceUnit().getName(), unitGroup.getReferenceUnit()
.getConversionFactor()));
return content.getQuantity();
}
private IDistribution convertDistribition(Uncertainty u,
String pedigreeMatrix) {
if (u == null || u.getDistributionType() == null)
return null;
switch (u.getDistributionType()) {
case LOG_NORMAL:
return new SPLogNormalDistribution(u.getParameter2Value(),
convertPedigreeMatrix(pedigreeMatrix));
case NORMAL:
return new SPNormalDistribution(u.getParameter2Value());
case TRIANGLE:
return new SPTriangleDistribution(u.getParameter1Value(),
u.getParameter3Value());
case UNIFORM:
return new SPUniformDistribution(u.getParameter1Value(),
u.getParameter2Value());
default:
return null;
}
}
private SPPedigreeMatrix convertPedigreeMatrix(String pedigreeMatrix) {
if (pedigreeMatrix == null)
return null;
SPPedigreeMatrix spPedigreeMatrix = new SPPedigreeMatrix();
Map<PedigreeMatrixRow, Integer> bla = PedigreeMatrix
.fromString(pedigreeMatrix);
for (Map.Entry<PedigreeMatrixRow, Integer> entry : bla.entrySet()) {
switch (entry.getKey()) {
case COMPLETENESS:
spPedigreeMatrix.setCompleteness(String.valueOf(entry
.getValue()));
break;
case GEOGRAPHY:
spPedigreeMatrix.setGeographicalCorrelation(String
.valueOf(entry.getValue()));
break;
case RELIABILITY:
spPedigreeMatrix
.setReliability(String.valueOf(entry.getValue()));
break;
case TECHNOLOGY:
spPedigreeMatrix.setTechnologicalCorrelation(String
.valueOf(entry.getValue()));
break;
case TIME:
spPedigreeMatrix.setTemporalCorrelation(String.valueOf(entry
.getValue()));
break;
}
}
return spPedigreeMatrix;
}
}