package org.openlca.geo; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.openlca.core.database.FileStore; import org.openlca.core.database.IDatabase; import org.openlca.core.database.ParameterDao; import org.openlca.core.matrix.TechIndex; import org.openlca.core.model.Parameter; import org.openlca.core.model.descriptors.ImpactMethodDescriptor; import org.openlca.geo.kml.IKmlLoader; import org.openlca.geo.kml.KmlLoader; import org.openlca.geo.kml.LocationKml; import org.openlca.geo.parameter.ParameterCalculator; import org.openlca.geo.parameter.ParameterSet; import org.openlca.geo.parameter.ShapeFileFolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RegionalizationSetup { private final Logger log = LoggerFactory.getLogger(getClass()); private final IKmlLoader kmlLoader; final IDatabase database; final ImpactMethodDescriptor method; public boolean canCalculate; public List<LocationKml> kmlData; public ParameterSet parameterSet; /** * Initializes the resources for regionalized LCIA calculation. The field * <code>canCalculate</code> is false if a regionalized calculation cannot * be done. The respective error message is logged the in this case. */ public static RegionalizationSetup create(IDatabase db, ImpactMethodDescriptor method, TechIndex index) { return create(db, method, index, new KmlLoader(db)); } /** * Initializes the resources for regionalized LCIA calculation. The field * <code>canCalculate</code> is false if a regionalized calculation cannot * be done. The respective error message is logged the in this case. */ public static RegionalizationSetup create(IDatabase db, ImpactMethodDescriptor method, TechIndex index, IKmlLoader kmlLoader) { RegionalizationSetup setup = new RegionalizationSetup(db, method, kmlLoader); if (db == null || method == null || index == null) { setup.canCalculate = false; return setup; } try { setup.init(index); } catch (Exception e) { setup.canCalculate = false; setup.log.error("failed to create regionalization setup", e); } return setup; } private RegionalizationSetup(IDatabase database, ImpactMethodDescriptor method, IKmlLoader kmlLoader) { this.database = database; this.method = method; this.kmlLoader = kmlLoader; } private void init(TechIndex index) { canCalculate = true; List<Parameter> params = getShapeFileParameters(); if (params.isEmpty()) { log.warn("Cannot calculate regionalized LCIA because there is " + "no LCIA method with shapefile parameters selected."); canCalculate = false; return; } kmlData = kmlLoader.load(index); if (kmlData.isEmpty()) { log.warn("Cannot calculate regionalized LCIA because none of the " + "processes in the product system contains a KML feature."); canCalculate = false; return; } ShapeFileFolder folder = getShapeFileFolder(); if (!shapeFilesExist(folder, params)) { canCalculate = false; return; } try (ParameterCalculator pCalc = new ParameterCalculator(params, folder)) { parameterSet = pCalc.calculate(kmlData); } } private List<Parameter> getShapeFileParameters() { String query = "select m.parameters from ImpactMethod m where " + "m.id = :methodId"; ParameterDao dao = new ParameterDao(database); List<Parameter> all = dao.getAll(query, Collections.singletonMap("methodId", method.getId())); List<Parameter> params = new ArrayList<>(); for (Parameter param : all) { if (param == null || param.getExternalSource() == null) continue; if (!"SHAPE_FILE".equals(param.getSourceType())) continue; params.add(param); } return params; } private ShapeFileFolder getShapeFileFolder() { File dir = new FileStore(database).getFolder(method); if (dir == null || !dir.exists()) { log.warn("Cannot calculate regionalized LCIA because no shapefiles " + "where found (location for shapefiles is {})", dir); canCalculate = false; return null; } return new ShapeFileFolder(dir); } private boolean shapeFilesExist(ShapeFileFolder folder, List<Parameter> params) { if (folder == null) return false; List<String> shapeFiles = folder.getShapeFiles(); for (Parameter parameter : params) { String shapefile = parameter.getExternalSource(); if (shapeFiles.contains(shapefile)) continue; log.error("Cannot calculate regionalized LCIA because " + "shapefile {} referenced from parameter " + "{} does not exist", shapefile, parameter); return false; } return true; } }