All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.kamaladafrica.codicefiscale.city.impl.CityProviderImpl Maven / Gradle / Ivy

package it.kamaladafrica.codicefiscale.city.impl;

import static java.util.function.Function.identity;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import it.kamaladafrica.codicefiscale.City;
import it.kamaladafrica.codicefiscale.CodiceFiscale;
import it.kamaladafrica.codicefiscale.city.CityProvider;
import it.kamaladafrica.codicefiscale.city.algo.JaroWinklerAlgoritm;
import it.kamaladafrica.codicefiscale.city.algo.ScoreAlgoritm;
import it.kamaladafrica.codicefiscale.city.impl.csv.EsteriCsvSupplier;
import it.kamaladafrica.codicefiscale.city.impl.csv.ItaliaCsvSupplier;
import it.kamaladafrica.codicefiscale.utils.Pair;

public final class CityProviderImpl implements CityProvider {

	public static final double DEFAULT_MINIMUM_MATCH_SCORE = 0.8;
	public static final double EXACT_MATCH_SCORE = 1.0;

	static final String ITALIA_RESOURCE_PATH = "italia.csv";
	static final String ESTERI_RESOURCE_PATH = "esteri.csv";
	static final String ESTERI_CESSATI_RESOURCE_PATH = "esteri-cessati.csv";

	private final Map cityByName;
	private final Map cityByBelfiore;

	private final ScoreAlgoritm scoreAlgoritm;
	private final double minimumMatchScore;

	private CityProviderImpl(Set cities, ScoreAlgoritm scoreAlgoritm, double minimumMatchScore) {
		this.scoreAlgoritm = Objects.requireNonNull(scoreAlgoritm);
		this.minimumMatchScore = minimumMatchScore;
		this.cityByName = Collections
				.unmodifiableMap(cities.stream().collect(Collectors.toMap(CityProviderImpl::cityName, identity())));
		this.cityByBelfiore = Collections
				.unmodifiableMap(cities.stream().collect(Collectors.toMap(City::getBelfiore, identity())));
	}

	private static String cityName(City city) {
		return String.format("%s(%s)", city.getName(), city.getProv());
	}

	private static String normalize(String s) {
		if (s == null || s.isEmpty()) {
			return "";
		}
		return s.toUpperCase(CodiceFiscale.LOCALE);
	}

	@Override
	public List findAll() {
		return Collections.unmodifiableList(
				cityByName.values().stream().sorted(Comparator.comparing(City::getName)).collect(Collectors.toList()));
	}

	@Override
	public City findByName(String name) {
		City result = null;
		final String term = normalize(name);
		if (!term.isEmpty()) {

			result = cityByName.get(term);
			if (minimumMatchScore != EXACT_MATCH_SCORE && result == null) {
				result = cityByName.entrySet().stream()
						.map(e -> Pair.of(e.getValue(), scoreAlgoritm.apply(term, e.getKey())))
						.filter(e -> e.getValue() >= minimumMatchScore).max(Comparator.comparing(Entry::getValue))
						.map(Entry::getKey).orElse(null);
			}
		}

		if (result == null) {
			throw new IllegalArgumentException("not found: " + term);
		}
		return result;
	}

	@Override
	public City findByBelfiore(String belfiore) {
		final String term = normalize(belfiore);
		City result = cityByBelfiore.get(term);
		if (result == null) {
			throw new IllegalArgumentException("not found: " + term);
		}
		return result;
	}

	public static CityProviderImpl ofDefault() {
		return of(defaultSupplier(), DEFAULT_MINIMUM_MATCH_SCORE);
	}

	public static CityProviderImpl of(Supplier> supplier, double minimumMatchScore) {
		return of(supplier.get(), minimumMatchScore);
	}

	public static CityProviderImpl of(Set cities, double minimumMatchScore) {
		return of(cities, new JaroWinklerAlgoritm(), minimumMatchScore);
	}

	public static CityProviderImpl of(Set cities, ScoreAlgoritm scoreAlgoritm, double minimumMatchScore) {
		return new CityProviderImpl(cities, scoreAlgoritm, minimumMatchScore);
	}

	public static CityProviderImpl of(Supplier> supplier) {
		return of(supplier.get(), DEFAULT_MINIMUM_MATCH_SCORE);
	}

	public static CityProviderImpl of(Set cities) {
		return of(cities, DEFAULT_MINIMUM_MATCH_SCORE);
	}

	private static Supplier> defaultSupplier() {
		return () -> CompositeCityStreamSupplier
				.of(ItaliaCsvSupplier.of(CityProviderImpl.class.getResource(ITALIA_RESOURCE_PATH)),
						EsteriCsvSupplier.of(CityProviderImpl.class.getResource(ESTERI_RESOURCE_PATH)),
						EsteriCsvSupplier.of(CityProviderImpl.class.getResource(ESTERI_CESSATI_RESOURCE_PATH)))
				.get().collect(Collectors.toSet());
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy