<commit_before>package org.openlca.app.results.contributions.locations;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.openlca.app.util.CostResultDescriptor;
import org.openlca.core.matrix.FlowIndex;
import org.openlca.core.matrix.IndexFlow;
import org.openlca.core.model.Location;
import org.openlca.core.model.descriptors.FlowDescriptor;
import org.openlca.core.model.descriptors.ImpactDescriptor;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.openlca.core.results.Contribution;
import org.openlca.core.results.ContributionResult;

class TreeContentProvider implements ITreeContentProvider {

	private final ContributionResult result;
	private final LocationPage page;

	public TreeContentProvider(LocationPage page) {
		this.page = page;
		this.result = page.result;
	}

	@Override
	public Object[] getElements(Object obj) {
		if (obj == null)
			return new Object[0];
		if (obj instanceof Object[])
			return (Object[]) obj;
		if (obj instanceof Collection) {
			Collection<?> coll = (Collection<?>) obj;
			return coll.toArray();
		}
		return new Object[0];
	}

	@Override
	public Object[] getChildren(Object obj) {
		if (!(obj instanceof Contribution))
			return null;
		Contribution<?> c = (Contribution<?>) obj;

		// calculated contributions are cached
		if (c.childs != null && !c.childs.isEmpty())
			return c.childs.toArray();

		// leaf of the contribution tree
		if (!(c.item instanceof Location))
			return null;

		Location loc = (Location) c.item;
		Object selection = page.getSelection();
		Stream<Contribution<?>> stream = null;
		if (selection instanceof FlowDescriptor) {
			stream = contributions(loc, (FlowDescriptor) selection);
		} else if (selection instanceof CostResultDescriptor) {
			stream = contributions(loc, (CostResultDescriptor) selection);
		} else if (selection instanceof ImpactDescriptor) {
			stream = contributions(loc, (ImpactDescriptor) selection);
		}

		if (stream == null)
			return null;

		// TODO apply cutoff
		c.childs = stream
				.filter(con -> con.amount != 0)
				.sorted((c1, c2) -> Double.compare(c2.amount, c1.amount))
				.collect(Collectors.toList());
		return c.childs.toArray();
	}

	@Override
	public Object getParent(Object obj) {
		return null;
	}

	@Override
	public boolean hasChildren(Object obj) {
		if (!(obj instanceof Contribution))
			return false;
		Contribution<?> c = (Contribution<?>) obj;
		if (c.childs != null && !c.childs.isEmpty())
			return false;
		return c.item instanceof Location;
	}

	@Override
	public void dispose() {
	}

	@Override
	public void inputChanged(
			Viewer viewer, Object old, Object newInput) {
	}

	private Stream<Contribution<?>> contributions(
			Location loc, FlowDescriptor flow) {

		// get the matrix row => IndexFlow
		FlowIndex flowIndex = result.flowIndex;
		int idx = flowIndex.isRegionalized
				? flowIndex.of(flow.id, loc.id)
				: flowIndex.of(flow.id);
		if (idx < 0)
			return null;
		IndexFlow iFlow = flowIndex.at(idx);
		if (iFlow == null)
			return null;

		// prepare the stream
		double total = result.getTotalFlowResult(iFlow);

		// in a regionalized result, the flow with the
		// given location can occur in processes that
		// have another location which is not the case
		// in a non-regionalized result
		if (flowIndex.isRegionalized) {
			return result.techIndex.content().stream().map(p -> {
				Contribution<?> c = Contribution.of(p.process);
				c.amount = result.getDirectFlowResult(p, iFlow);
				c.computeShare(total);
				return c;
			});
		} else {
			return processes(loc).stream().map(p -> {
				Contribution<?> c = Contribution.of(p);
				c.amount = result.getDirectFlowResult(p, iFlow);
				c.computeShare(total);
				return c;
			});
		}
	}

	private Stream<Contribution<?>> contributions(
			Location loc, CostResultDescriptor c) {
		double total = c.forAddedValue
				? -result.totalCosts
				: result.totalCosts;
		return processes(loc).stream().map(p -> {
			Contribution<?> con = Contribution.of(p);
			con.amount = c.forAddedValue
					? -result.getDirectCostResult(p)
					: result.getDirectCostResult(p);
			con.computeShare(total);
			return con;
		});
	}

	private Stream<Contribution<?>> contributions(
			Location loc, ImpactDescriptor impact) {

		double total = result.getTotalImpactResult(impact);
		if (!result.flowIndex.isRegionalized) {
			return processes(loc).stream().map(p -> {
				Contribution<?> c = Contribution.of(p);
				c.amount = result.getDirectImpactResult(p, impact);
				c.computeShare(total);
				return c;
			});
		}

		// first collect all flows in that location
		List<IndexFlow> flows = new ArrayList<>();
		result.flowIndex.each((i, iFlow) -> {
			if (loc == null && iFlow.location == null) {
				flows.add(iFlow);
				return;
			}
			if (loc == null || iFlow.location == null)<commit_msg>FlowIndex.isRegionalized is now a method<commit_after>package org.openlca.app.results.contributions.locations;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.openlca.app.util.CostResultDescriptor;
import org.openlca.core.matrix.FlowIndex;
import org.openlca.core.matrix.IndexFlow;
import org.openlca.core.model.Location;
import org.openlca.core.model.descriptors.FlowDescriptor;
import org.openlca.core.model.descriptors.ImpactDescriptor;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.openlca.core.results.Contribution;
import org.openlca.core.results.ContributionResult;

class TreeContentProvider implements ITreeContentProvider {

	private final ContributionResult result;
	private final LocationPage page;

	public TreeContentProvider(LocationPage page) {
		this.page = page;
		this.result = page.result;
	}

	@Override
	public Object[] getElements(Object obj) {
		if (obj == null)
			return new Object[0];
		if (obj instanceof Object[])
			return (Object[]) obj;
		if (obj instanceof Collection) {
			Collection<?> coll = (Collection<?>) obj;
			return coll.toArray();
		}
		return new Object[0];
	}

	@Override
	public Object[] getChildren(Object obj) {
		if (!(obj instanceof Contribution))
			return null;
		Contribution<?> c = (Contribution<?>) obj;

		// calculated contributions are cached
		if (c.childs != null && !c.childs.isEmpty())
			return c.childs.toArray();

		// leaf of the contribution tree
		if (!(c.item instanceof Location))
			return null;

		Location loc = (Location) c.item;
		Object selection = page.getSelection();
		Stream<Contribution<?>> stream = null;
		if (selection instanceof FlowDescriptor) {
			stream = contributions(loc, (FlowDescriptor) selection);
		} else if (selection instanceof CostResultDescriptor) {
			stream = contributions(loc, (CostResultDescriptor) selection);
		} else if (selection instanceof ImpactDescriptor) {
			stream = contributions(loc, (ImpactDescriptor) selection);
		}

		if (stream == null)
			return null;

		// TODO apply cutoff
		c.childs = stream
				.filter(con -> con.amount != 0)
				.sorted((c1, c2) -> Double.compare(c2.amount, c1.amount))
				.collect(Collectors.toList());
		return c.childs.toArray();
	}

	@Override
	public Object getParent(Object obj) {
		return null;
	}

	@Override
	public boolean hasChildren(Object obj) {
		if (!(obj instanceof Contribution))
			return false;
		Contribution<?> c = (Contribution<?>) obj;
		if (c.childs != null && !c.childs.isEmpty())
			return false;
		return c.item instanceof Location;
	}

	@Override
	public void dispose() {
	}

	@Override
	public void inputChanged(
			Viewer viewer, Object old, Object newInput) {
	}

	private Stream<Contribution<?>> contributions(
			Location loc, FlowDescriptor flow) {

		// get the matrix row => IndexFlow
		FlowIndex flowIndex = result.flowIndex;
		int idx = flowIndex.isRegionalized()
				? flowIndex.of(flow.id, loc.id)
				: flowIndex.of(flow.id);
		if (idx < 0)
			return null;
		IndexFlow iFlow = flowIndex.at(idx);
		if (iFlow == null)
			return null;

		// prepare the stream
		double total = result.getTotalFlowResult(iFlow);

		// in a regionalized result, the flow with the
		// given location can occur in processes that
		// have another location which is not the case
		// in a non-regionalized result
		if (flowIndex.isRegionalized()) {
			return result.techIndex.content().stream().map(p -> {
				Contribution<?> c = Contribution.of(p.process);
				c.amount = result.getDirectFlowResult(p, iFlow);
				c.computeShare(total);
				return c;
			});
		} else {
			return processes(loc).stream().map(p -> {
				Contribution<?> c = Contribution.of(p);
				c.amount = result.getDirectFlowResult(p, iFlow);
				c.computeShare(total);
				return c;
			});
		}
	}

	private Stream<Contribution<?>> contributions(
			Location loc, CostResultDescriptor c) {
		double total = c.forAddedValue
				? -result.totalCosts
				: result.totalCosts;
		return processes(loc).stream().map(p -> {
			Contribution<?> con = Contribution.of(p);
			con.amount = c.forAddedValue
					? -result.getDirectCostResult(p)
					: result.getDirectCostResult(p);
			con.computeShare(total);
			return con;
		});
	}

	private Stream<Contribution<?>> contributions(
			Location loc, ImpactDescriptor impact) {

		double total = result.getTotalImpactResult(impact);
		if (!result.flowIndex.isRegionalized()) {
			return processes(loc).stream().map(p -> {
				Contribution<?> c = Contribution.of(p);
				c.amount = result.getDirectImpactResult(p, impact);
				c.computeShare(total);
				return c;
			});
		}

		// first collect all flows in that location
		List<IndexFlow> flows = new ArrayList<>();
		result.flowIndex.each((i, iFlow) -> {
			if (loc == null && iFlow.location == null) {
				flows.add(iFlow);
				return;
			}
			if (loc == null || iFlow.location == null)
{'fraction_non_alphanumeric': 0.12675216224276767, 'fraction_numerical': 0.0015906153693210062, 'mean_word_length': 3.9459193706981317, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5741588', 'n_tokens_mistral': 3554, 'n_tokens_neox': 3110, 'n_words': 775}