cdc.issues.checks.RulesCatalogImpl Maven / Gradle / Ivy
package cdc.issues.checks;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import cdc.issues.checks.IssuesDetector.Factory;
import cdc.issues.rules.Rule;
import cdc.issues.rules.RuleId;
import cdc.util.lang.Checks;
import cdc.util.lang.Introspection;
/**
* Default implementation of {@link RulesCatalog}.
*
* @author Damien Carbonne
*/
public class RulesCatalogImpl implements RulesCatalog {
/**
* (domain -> Set[Rule]) map.
*/
private final Map> domainToRules = new HashMap<>();
/**
* Set of Rules.
*/
private final Set rules = new HashSet<>();
private final Map idToRules = new HashMap<>();
/**
* Set of factories.
*/
private final Set> factories = new HashSet<>();
/**
* ((Rule, Data class) -> Descriptor) map.
*/
private final Map> ruleDataClassToFactory = new HashMap<>();
/**
* (dataClass -> Set) map.
*/
private final Map, Set>> dataClassToFactories = new HashMap<>();
private static record RuleClassKey(Rule rule,
Class> cls) {
}
public RulesCatalogImpl() {
super();
}
public RulesCatalogImpl register(Rule rule) {
Checks.isNotNull(rule, "rule");
Checks.doesNotContain(rules, rule, "rules");
Checks.doesNotContainKey(idToRules, rule.getId(), "idToRules");
rules.add(rule);
idToRules.put(rule.getId(), rule);
final Set set = domainToRules.computeIfAbsent(rule.getId().getDomain(), k -> new HashSet<>());
set.add(rule);
return this;
}
public RulesCatalogImpl register(IssuesDetector.Factory factory) {
Checks.isNotNull(factory, "factory");
Checks.doesNotContain(factories, factory, "factory");
factories.add(factory);
final Set> set =
dataClassToFactories.computeIfAbsent(factory.getDataClass(), k -> new HashSet<>());
set.add(factory);
for (final Rule rule : factory.getSupportedRules()) {
final RuleClassKey key = new RuleClassKey(rule, factory.getDataClass());
if (!hasRule(rule)) {
register(rule);
}
if (ruleDataClassToFactory.containsKey(key)) {
throw new IllegalArgumentException("Duplicate factory for " + key);
} else {
ruleDataClassToFactory.put(key, factory);
}
}
return this;
}
@Override
public Set getDomains() {
return domainToRules.keySet();
}
@Override
public Set getRules() {
return rules;
}
@Override
public Set getRules(String domain) {
return domainToRules.getOrDefault(domain, Collections.emptySet());
}
@Override
public Optional getRule(RuleId id) {
return Optional.ofNullable(idToRules.get(id));
}
@Override
public Set> getFactories() {
return factories;
}
@Override
public Set> getFactories(Class dataClass) {
final Set> set =
dataClassToFactories.getOrDefault(dataClass, Collections.emptySet());
return Introspection.uncheckedCast(set);
}
@Override
public Optional> getFactory(Rule rule,
Class dataClass) {
final RuleClassKey key = new RuleClassKey(rule, dataClass);
final Factory value = Introspection.uncheckedCast(ruleDataClassToFactory.get(key));
return Optional.ofNullable(value);
}
}