package org.openlca.geo.parameter; import java.io.Closeable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.geotools.data.DataStore; import org.openlca.core.model.Parameter; import org.openlca.geo.kml.FeatureType; import org.openlca.geo.kml.KmlFeature; import org.openlca.geo.kml.LocationKml; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ParameterCalculator implements Closeable { private final Logger log = LoggerFactory.getLogger(getClass()); private Map<String, List<String>> parameters; private Map<String, DataStore> stores; private Map<String, Double> defaults; private ParameterCache cache; public ParameterCalculator(List<Parameter> parameters, ShapeFileFolder folder) { this.parameters = groupByShapeFile(parameters); stores = openStores(this.parameters.keySet(), folder); cache = new ParameterCache(folder); defaults = new HashMap<>(); for (Parameter p : parameters) { defaults.put(p.getName(), p.getValue()); } } @Override public void close() { for (DataStore dataStore : stores.values()) { dataStore.dispose(); } } public ParameterSet calculate(List<LocationKml> kmlData) { ParameterSet set = new ParameterSet(defaults); if (parameters.isEmpty()) return set; for (LocationKml data : kmlData) { KmlFeature feature = data.kmlFeature; if (feature == null || feature.type == FeatureType.EMPTY) continue; Map<String, Double> parameters = calculate(data.locationId, feature); set.put(data.locationId, parameters); } return set; } public Map<String, Double> calculate(long locationId, KmlFeature feature) { Map<String, Double> parameterMap = new HashMap<String, Double>(); for (String shapeFile : parameters.keySet()) { Map<String, Double> shares = getShares(locationId, feature, shapeFile); log.debug("Calculating parameters for location {}", locationId); DataStore store = stores.get(shapeFile); FeatureCalculator calculator = new FeatureCalculator(store, defaults); List<String> params = parameters.get(shapeFile); Map<String, Double> result = calculator.calculate(feature, params, shares); if (result != null) { parameterMap.putAll(result); } } fillZeros(parameterMap); return parameterMap; } /** * Returns the intersection shares of the geometries in the shapefile for * the given feature: geometry ID -> share */ private Map<String, Double> getShares(long locationId, KmlFeature feature, String shapeFile) { Map<String, Double> shares = cache.load(locationId, shapeFile); if (shares == null) { DataStore store = stores.get(shapeFile); IntersectionsCalculator calculator = new IntersectionsCalculator(store); log.debug("Calculating shares for location " + locationId); shares = calculator.calculate(feature); cache.save(locationId, shapeFile, shares); } HashMap<String, Double> r = new HashMap<>(); for (Entry<String, Double> e : shares.entrySet()) { Double val = e.getValue(); if (val == null || Val.isZero(val)) continue; r.put(e.getKey(), val); } return r; } private void fillZeros(Map<String, Double> results) { for (String param : defaults.keySet()) { Double r = results.get(param); if (r == null) { results.put(param, 0d); } } } private Map<String, DataStore> openStores(Set<String> shapeFiles, ShapeFileFolder folder) { Map<String, DataStore> stores = new HashMap<>(); for (String shapeFile : shapeFiles) { DataStore store = folder.openDataStore(shapeFile); stores.put(shapeFile, store); } return stores; } private Map<String, List<String>> groupByShapeFile(List<Parameter> params) { Map<String, List<String>> groups = new HashMap<>(); for (Parameter param : params) { String shapeFile = param.getExternalSource(); List<String> group = groups.get(shapeFile); if (group == null) { group = new ArrayList<>(); groups.put(shapeFile, group); } group.add(param.getName()); } return groups; } }