<commit_before>package org.openlca.io.openepd.io;

import org.openlca.core.model.Epd;
import org.openlca.core.model.EpdModule;
import org.openlca.core.model.ImpactCategory;
import org.openlca.util.Strings;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

final class ExportMapping {

	private ExportMapping() {
	}

	static MappingModel build(Epd epd) {
		if (epd == null)
			return MappingModel.empty();

		// init the mappings
		var mappings = new ArrayList<MethodMapping>();
		for (var mod : epd.modules) {
			var model = of(mod, mappings);
			if (model == null)
				continue;
			for (var impact : mod.result.impactResults) {
				var indicator = impact.indicator;
				if (indicator == null)
					continue;
				var row = rowOf(indicator, model);
				row.values().put(scopeOf(mod), mod.multiplier * impact.amount);
			}
		}

		// sort & map
		for (var model : mappings) {
			model.scopes().sort(Strings::compare);
			model.entries().sort((r1, r2) -> {
				var i1 = r1.indicator();
				var i2 = r2.indicator();
				return i1 != null && i2 != null
					? Strings.compare(i1.name, i2.name)
					: 0;
			});
			initMappings(model);
		}
		return new MappingModel(mappings);
	}

	private static MethodMapping of(EpdModule mod, List<MethodMapping> models) {
		if (mod == null
			|| Strings.nullOrEmpty(mod.name)
			|| mod.result == null
			|| mod.result.impactResults.isEmpty())
			return null;
		var method = mod.result.impactMethod;
		MethodMapping model = null;
		for (var existing : models) {
			if (Objects.equals(method, existing.method())) {
				model = existing;
				break;
			}
		}
		if (model == null) {
			model = new MethodMapping().method(method);
			models.add(model);
		}
		var scope = scopeOf(mod);
		if (!model.scopes().contains(scope)) {
			model.scopes().add(scope);
		}
		return model;
	}

	private static String scopeOf(EpdModule mod) {
		if (mod == null || mod.name == null)
			return "?";
		var scope = Vocab.findScope(mod.name);
		return scope.isPresent()
			? scope.get().code()
			: mod.name;
	}

	private static IndicatorMapping rowOf(ImpactCategory indicator, MethodMapping model) {
		for (var row : model.entries()) {
			if (Objects.equals(indicator, row.indicator()))
				return row;
		}
		var row = new IndicatorMapping().indicator(indicator);
		model.entries().add(row);
		return row;
	}

	private static void initMappings(MethodMapping model) {

		var queue = EnumSet.allOf(Vocab.Indicator.class);
		Supplier<Vocab.Indicator> next = () -> {
			var i = queue.iterator().next();
			queue.remove(i);
			return i;
		};

		while (!queue.isEmpty()) {
			var epdInd = next.get();
			var match = Match.empty();
			for (var row : model.entries()) {
				var nextMatch = Match.of(epdInd, row);
				if (match.isBetterThan(nextMatch))
					continue;
				var prevMatch = Match.of(row);
				if (prevMatch.isBetterThan(nextMatch))
					continue;

				match.release();
				if (prevMatch.isBound()) {
					if (prevMatch.indicator() != epdInd) {
						queue.add(prevMatch.indicator());<commit_msg>try to match an EPD method in the export<commit_after>package org.openlca.io.openepd.io;

import org.openlca.core.model.Epd;
import org.openlca.core.model.EpdModule;
import org.openlca.core.model.ImpactCategory;
import org.openlca.util.Strings;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

final class ExportMapping {

	private ExportMapping() {
	}

	static MappingModel build(Epd epd) {
		if (epd == null)
			return MappingModel.empty();

		// init the mappings
		var mappings = new ArrayList<MethodMapping>();
		for (var mod : epd.modules) {
			var mapping = of(mod, mappings);
			if (mapping == null)
				continue;
			for (var impact : mod.result.impactResults) {
				var indicator = impact.indicator;
				if (indicator == null)
					continue;
				var row = rowOf(indicator, mapping);
				row.values().put(scopeOf(mod), mod.multiplier * impact.amount);
			}
		}

		// sort & map
		for (var model : mappings) {
			model.scopes().sort(Strings::compare);
			model.entries().sort((r1, r2) -> {
				var i1 = r1.indicator();
				var i2 = r2.indicator();
				return i1 != null && i2 != null
					? Strings.compare(i1.name, i2.name)
					: 0;
			});
			initMappings(model);
		}
		return new MappingModel(mappings);
	}

	private static MethodMapping of(EpdModule mod, List<MethodMapping> models) {
		if (mod == null
			|| Strings.nullOrEmpty(mod.name)
			|| mod.result == null
			|| mod.result.impactResults.isEmpty())
			return null;
		var method = mod.result.impactMethod;
		MethodMapping mapping = null;
		for (var existing : models) {
			if (Objects.equals(method, existing.method())) {
				mapping = existing;
				break;
			}
		}
		if (mapping == null) {
			mapping = new MethodMapping().method(method);
			models.add(mapping);
		}
		var scope = scopeOf(mod);
		if (!mapping.scopes().contains(scope)) {
			mapping.scopes().add(scope);
		}

		// find an EPD method
		if (method != null) {
			Vocab.Method candidate = null;
			double score = 0.0001;
			for (var m : Vocab.Method.values()) {
				var nextScore = m.matchScoreOf(method.name);
				if (nextScore > score) {
					candidate = m;
					score = nextScore;
				}
			}
			mapping.epdMethod(candidate);
		}

		return mapping;
	}

	private static String scopeOf(EpdModule mod) {
		if (mod == null || mod.name == null)
			return "?";
		var scope = Vocab.findScope(mod.name);
		return scope.isPresent()
			? scope.get().code()
			: mod.name;
	}

	private static IndicatorMapping rowOf(
		ImpactCategory indicator, MethodMapping mapping) {
		for (var row : mapping.entries()) {
			if (Objects.equals(indicator, row.indicator()))
				return row;
		}
		var row = new IndicatorMapping().indicator(indicator);
		mapping.entries().add(row);
		return row;
	}

	private static void initMappings(MethodMapping model) {

		var queue = EnumSet.allOf(Vocab.Indicator.class);
		Supplier<Vocab.Indicator> next = () -> {
			var i = queue.iterator().next();
			queue.remove(i);
			return i;
		};

		while (!queue.isEmpty()) {
			var epdInd = next.get();
			var match = Match.empty();
			for (var row : model.entries()) {
				var nextMatch = Match.of(epdInd, row);
				if (match.isBetterThan(nextMatch))
					continue;
				var prevMatch = Match.of(row);
				if (prevMatch.isBetterThan(nextMatch))
					continue;

				match.release();
				if (prevMatch.isBound()) {
					if (prevMatch.indicator() != epdInd) {
						queue.add(prevMatch.indicator());
{'fraction_non_alphanumeric': 0.14457464617257648, 'fraction_numerical': 0.0041089636280627, 'mean_word_length': 3.337953795379538, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 14, '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': '5527539', 'n_tokens_mistral': 2622, 'n_tokens_neox': 2208, 'n_words': 504}