131 lines
4.4 KiB
Java
131 lines
4.4 KiB
Java
package it.cavallium.warppi.math.rules.dsl;
|
|
|
|
import it.cavallium.warppi.math.Function;
|
|
import it.cavallium.warppi.math.MathContext;
|
|
import it.cavallium.warppi.math.rules.Rule;
|
|
import it.cavallium.warppi.math.rules.RuleType;
|
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* A <code>Rule</code> which uses <code>Pattern</code>s to match and replace functions.
|
|
*/
|
|
public class PatternRule implements Rule {
|
|
private final String ruleName;
|
|
private final RuleType ruleType;
|
|
private final Pattern target;
|
|
private final List<Pattern> replacements;
|
|
|
|
/**
|
|
* Constructs a <code>PatternRule</code> with the given name, type and <code>Pattern</code>s.
|
|
*
|
|
* @param ruleName the name of the rule.
|
|
* @param ruleType the type of the rule.
|
|
* @param target the <code>Pattern</code> used to match functions and capture sub-functions.
|
|
* @param replacements the list of <code>Pattern</code>s used to construct replacement functions.
|
|
* All sub-functions which are referenced within these <code>Pattern</code>s must be captured
|
|
* by <code>target</code>, otherwise the {@link #execute} method will throw an
|
|
* {@link UndefinedSubFunction} exception when constructing the replacement functions.
|
|
*/
|
|
public PatternRule(
|
|
final String ruleName,
|
|
final RuleType ruleType,
|
|
final Pattern target,
|
|
final List<Pattern> replacements
|
|
) {
|
|
this.ruleName = ruleName;
|
|
this.ruleType = ruleType;
|
|
this.target = target;
|
|
this.replacements = replacements;
|
|
}
|
|
|
|
/**
|
|
* Constructs a <code>PatternRule</code> with the given name, type and <code>Pattern</code>s.
|
|
*
|
|
* @param ruleName the name of the rule.
|
|
* @param ruleType the type of the rule.
|
|
* @param target the <code>Pattern</code> used to match functions and capture sub-functions.
|
|
* @param replacements the <code>Pattern</code>s used to construct replacement functions.
|
|
* All sub-functions which are referenced within these <code>Pattern</code>s must be captured
|
|
* by <code>target</code>, otherwise the {@link #execute} method will throw an
|
|
* {@link UndefinedSubFunction} exception when constructing the replacement functions.
|
|
*/
|
|
public PatternRule(
|
|
final String ruleName,
|
|
final RuleType ruleType,
|
|
final Pattern target,
|
|
final Pattern... replacements
|
|
) {
|
|
this(ruleName, ruleType, target, Arrays.asList(replacements));
|
|
}
|
|
|
|
@Override
|
|
public String getRuleName() {
|
|
return ruleName;
|
|
}
|
|
|
|
@Override
|
|
public RuleType getRuleType() {
|
|
return ruleType;
|
|
}
|
|
|
|
/**
|
|
* @return the <code>Pattern</code> used to match functions and capture sub-functions.
|
|
*/
|
|
public Pattern getTarget() {
|
|
return target;
|
|
}
|
|
|
|
/**
|
|
* @return the list of <code>Pattern</code>s used to construct replacement functions.
|
|
*/
|
|
public List<Pattern> getReplacements() {
|
|
return replacements;
|
|
}
|
|
|
|
/**
|
|
* @throws UndefinedSubFunctionException if the target pattern matches, but it doesn't capture all of the
|
|
* sub-functions required by the replacement patterns.
|
|
* This exception will never be thrown for well-formed rules (like the ones
|
|
* returned by {@link RulesDsl#makeRules}), in which the target pattern
|
|
* correctly captures all sub-functions referenced by the replacement patterns.
|
|
*/
|
|
@Override
|
|
public ObjectArrayList<Function> execute(final Function func) {
|
|
return target.match(func)
|
|
.map(subFunctions -> applyReplacements(func.getMathContext(), subFunctions))
|
|
.orElse(null);
|
|
}
|
|
|
|
private ObjectArrayList<Function> applyReplacements(
|
|
final MathContext mathContext,
|
|
final Map<String, Function> subFunctions
|
|
) {
|
|
return replacements.stream()
|
|
.map(replacement -> replacement.replace(mathContext, subFunctions))
|
|
.collect(Collectors.toCollection(ObjectArrayList::new));
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(final Object o) {
|
|
if (!(o instanceof PatternRule)) {
|
|
return false;
|
|
}
|
|
final PatternRule other = (PatternRule) o;
|
|
return ruleName.equals(other.ruleName)
|
|
&& ruleType == other.ruleType
|
|
&& target.equals(other.target)
|
|
&& replacements.equals(other.replacements);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(ruleName, ruleType, target, replacements);
|
|
}
|
|
}
|