package org.openlca.app.results.contributions.locations;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.openlca.app.util.CostResultDescriptor;
import org.openlca.core.database.EntityCache;
import org.openlca.core.model.Location;
import org.openlca.core.model.descriptors.BaseDescriptor;
import org.openlca.core.model.descriptors.FlowDescriptor;
import org.openlca.core.model.descriptors.ImpactCategoryDescriptor;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.openlca.core.results.ContributionItem;
import org.openlca.core.results.ContributionResultProvider;
import org.openlca.core.results.ContributionSet;
import org.openlca.core.results.Contributions;
/**
* Creates the content that should be displayed in the location tree for a given
* selection.
*/
class TreeContentBuilder {
private LocationPage page;
private ContributionResultProvider<?> result;
private Map<Location, List<ProcessDescriptor>> index = new HashMap<>();
TreeContentBuilder(LocationPage page) {
this.page = page;
this.result = page.result;
initProcessIndex();
}
private void initProcessIndex() {
if (result == null)
return;
EntityCache cache = result.cache;
for (ProcessDescriptor process : result.getProcessDescriptors()) {
Location location = null;
if (process.getLocation() != null) {
location = cache.get(Location.class, process.getLocation());
}
List<ProcessDescriptor> list = index.get(location);
if (list == null) {
list = new ArrayList<>();
index.put(location, list);
}
list.add(process);
}
}
List<LocationItem> build(ContributionSet<Location> set,
BaseDescriptor selection, double total) {
List<LocationItem> items = new ArrayList<>();
for (ContributionItem<Location> contribution : set.contributions) {
if (Math.abs(contribution.share) < page.cutoff)
continue;
if (contribution.amount == 0 && page.skipZeros)
continue;
items.add(new LocationItem(contribution));
}
Contributions.calculate(index.keySet(), total, location -> {
LocationItem elem = getItem(items, location);
if (elem == null)
return 0;
List<ProcessDescriptor> list = index.get(location);
double amount = 0;
for (ProcessDescriptor p : list) {
double r = getSingleResult(p, selection);
if (r == 0 && page.skipZeros)
continue;
ContributionItem<ProcessDescriptor> item = new ContributionItem<>();
item.rest = p == null;
item.item = p;
item.amount = r;
item.share = r / total;
elem.processContributions.add(item);
amount += r;
}
Contributions.sortDescending(elem.processContributions);
return amount;
});
return items;
}
private double getSingleResult(ProcessDescriptor process,
BaseDescriptor selection) {
if (process == null || selection == null)
return 0;
if (selection instanceof ImpactCategoryDescriptor) {
ImpactCategoryDescriptor d = (ImpactCategoryDescriptor) selection;
return result.getSingleImpactResult(process, d).value;
}
if (selection instanceof FlowDescriptor) {
FlowDescriptor d = (FlowDescriptor) selection;
return result.getSingleFlowResult(process, d).value;
}
if (selection instanceof CostResultDescriptor) {
double costs = result.getSingleCostResult(process);
CostResultDescriptor d = (CostResultDescriptor) selection;
return d.forAddedValue ? costs == 0 ? 0 : -costs : costs;
}
return 0;
}
private LocationItem getItem(List<LocationItem> items, Location location) {
for (LocationItem item : items) {
Location other = item.contribution.item;
if (Objects.equals(other, location))
return item;
}
return null;
}
}