/**
* Copyright (C) 2022, 2024, 2025 Adrien Hopkins
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package sevenUnitsGUI;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import sevenUnits.unit.LinearUnit;
import sevenUnits.unit.Metric;
import sevenUnits.unit.UnitPrefix;
/**
* A search rule that applies a certain set of prefixes to a unit. It always
* includes the original unit in the output map.
*
* @since v0.4.0
* @since 2022-07-06
*/
public final class PrefixSearchRule implements
Function, Map> {
/**
* A rule that does not add any prefixed versions of units.
*
* @since v0.4.0
*/
public static final PrefixSearchRule NO_PREFIXES = getUniversalRule(
Set.of());
/**
* A rule that gives every unit a common set of prefixes.
*
* @since v0.4.0
*/
public static final PrefixSearchRule COMMON_PREFIXES = getCoherentOnlyRule(
Set.of(Metric.MILLI, Metric.KILO));
/**
* A rule that gives every unit all metric prefixes.
*
* @since v0.4.0
*/
public static final PrefixSearchRule ALL_METRIC_PREFIXES = getCoherentOnlyRule(
Metric.ALL_PREFIXES);
/**
* Gets a rule that applies the provided prefixes to coherent units only (as
* defined by {@link LinearUnit#isCoherent}), except the kilogram
* (specifically, units named "kilogram").
*
* @param prefixes prefixes to apply
* @return prefix rule
* @since v0.4.0
* @since 2022-07-06
*/
public static final PrefixSearchRule getCoherentOnlyRule(
Set prefixes) {
return new PrefixSearchRule(prefixes,
u -> u.isCoherent() && !u.getName().equals("kilogram"));
}
/**
* Gets a rule that applies the provided prefixes to all units.
*
* @param prefixes prefixes to apply
* @return prefix rule
* @since v0.4.0
* @since 2022-07-06
*/
public static final PrefixSearchRule getUniversalRule(
Set prefixes) {
return new PrefixSearchRule(prefixes, u -> true);
}
/**
* The set of prefixes that will be applied to the unit.
*/
private final Set prefixes;
/**
* Determines which units are given prefixes.
*/
private final Predicate prefixableUnitRule;
/**
* @param prefixes prefixes to add to units
* @param prefixableUnitRule function that determines which units get
* prefixes
* @since v0.4.0
* @since 2022-07-06
*/
public PrefixSearchRule(Set prefixes,
Predicate prefixableUnitRule) {
this.prefixes = Collections.unmodifiableSet(new HashSet<>(prefixes));
this.prefixableUnitRule = prefixableUnitRule;
}
@Override
public Map apply(Entry t) {
final Map outputUnits = new HashMap<>();
final String originalName = t.getKey();
final LinearUnit originalUnit = t.getValue();
outputUnits.put(originalName, originalUnit);
if (this.prefixableUnitRule.test(originalUnit)) {
for (final UnitPrefix prefix : this.prefixes) {
outputUnits.put(prefix.getName() + originalName,
originalUnit.withPrefix(prefix));
}
}
return Collections.unmodifiableMap(outputUnits);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof PrefixSearchRule))
return false;
final PrefixSearchRule other = (PrefixSearchRule) obj;
return Objects.equals(this.prefixableUnitRule, other.prefixableUnitRule)
&& Objects.equals(this.prefixes, other.prefixes);
}
/**
* @return rule that determines which units get prefixes
* @since v0.4.0
* @since 2022-07-09
*/
public Predicate getPrefixableUnitRule() {
return this.prefixableUnitRule;
}
/**
* @return the prefixes that are applied by this rule
* @since v0.4.0
* @since 2022-07-06
*/
public Set getPrefixes() {
return this.prefixes;
}
@Override
public int hashCode() {
return Objects.hash(this.prefixableUnitRule, this.prefixes);
}
@Override
public String toString() {
return "Apply the following prefixes: " + this.prefixes;
}
}