cdc.issues.checks.RulesCatalog Maven / Gradle / Ivy
package cdc.issues.checks;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import cdc.issues.DataSource;
import cdc.issues.Issue;
import cdc.issues.IssuesHandler;
import cdc.issues.Project;
import cdc.issues.locations.LocatedObject;
import cdc.issues.rules.ConfiguredRule;
import cdc.issues.rules.Profile;
import cdc.issues.rules.Rule;
import cdc.issues.rules.RuleId;
import cdc.util.events.ProgressController;
import cdc.util.events.ProgressSupplier;
import cdc.util.lang.Checks;
import cdc.util.lang.NotFoundException;
/**
* Interface implemented by classes that manage domains, rules and
* associated services.
*
* @author Damien Carbonne
*/
@Deprecated(since = "2023-10-21", forRemoval = true)
public interface RulesCatalog {
/**
* @return A set of all known domains.
*/
public Set getDomains();
/**
* @param domain The domain
* @return {@code true} if {@code domain} is known.
*/
public default boolean hasDomain(String domain) {
return getDomains().contains(domain);
}
/**
* @return A set of all known {@link Rule}s.
*/
public Set getRules();
/**
* Returns the rule that has a given id.
*
* @param id The id.
* @return The rule identified by {@code id}.
*/
public Optional getRule(RuleId id);
/**
* Returns {@code true} if a {@link Rule} is registered.
*
* @param rule The rule
* @return {@code true} if {@code rule} is registered.
*/
public default boolean hasRule(Rule rule) {
return getRules().contains(rule);
}
/**
* Returns {@code true} if a {@link Rule} with an id is registered.
*
* @param id The id.
* @return {@code true} if a {@link Rule} identified with {@code id} is registered.
*/
public default boolean hasRule(RuleId id) {
return getRule(id).isPresent();
}
/**
* Returns a set of all known {@link Rule}s belonging to a domain.
*
* @param domain The domain.
* @return A set of {@link Rule}s belonging to {@code domain}.
*/
public default Set getRules(String domain) {
return getRules().stream()
.filter(rule -> rule.getDomain().equals(domain))
.collect(Collectors.toSet());
}
/**
* @return A set of all known {@link IssuesDetector.Factory}s.
*/
public Set> getFactories();
/**
* Returns a set of all {@link IssuesDetector.Factory}s registered for a data class.
*
* @param The data type.
* @param dataClass The data class.
* @return A set of all {@link IssuesDetector.Factory}s registered for {@code dataClass}.
*/
public Set> getFactories(Class dataClass);
/**
* Returns the {@link IssuesDetector.Factory} associated to a Rule and
* a Class, or {@code null}.
*
* @param The data type.
* @param rule The rule.
* @param dataClass The data class.
* @return The {@link IssuesDetector.Factory} associated to {@code rule}
* and {@code dataClass}, or {@code null}.
*/
public Optional> getFactory(Rule rule,
Class dataClass);
/**
* Returns {@code true} if an {@link IssuesDetector.Factory}
* is registered for a Rule and a Class.
*
* @param rule The rule.
* @param dataClass The data class
* @return {@code true} if an {@link IssuesDetector.Factory} is
* registered for {@code rule} and {@code dataClass}.
*/
public default boolean hasDescriptor(Rule rule,
Class> dataClass) {
return getFactory(rule, dataClass).isPresent();
}
/**
* Creates and configures one IssuesDetector for one rule and parameters.
*
* @param The data type.
* @param project The project for which the detector is created.
* @param snapshot The snapshot for which the detector is created.
* @param configuredRule The configured rule.
* @param dataClass The data class.
* @return An IssueDetector matching {@code configuredRule}
* and {@code dataClass}, and configured with {@code project}
* and {@code snapshot}.
* @throws NotFoundException When no matching IssuesDetector could be found.
*/
public default IssuesDetector createIssuesDetector(String project,
String snapshot,
ConfiguredRule configuredRule,
Class dataClass) {
final IssuesDetector.Factory factory =
getFactory(configuredRule.getRule(), dataClass).orElseThrow(() -> new NotFoundException("No factory for "
+ configuredRule.getRule().getName()));
final Set crules = new HashSet<>();
crules.add(configuredRule);
return factory.create(project, snapshot, crules);
}
/**
* Creates and configures an appropriate IssuesDetector,
* and applies it to data provided by a Spliterator.
*
* @param The data type.
* @param project The project for which the detector is created.
* @param snapshot The snapshot for which the detector is created.
* @param configuredRule The configured rule.
* @param dataClass The data class.
* @param spliterator The data spliterator.
* @param issuesHandler The issues handler that will collect issues.
* @param controller The progress controller.
*/
public default void apply(String project,
String snapshot,
ConfiguredRule configuredRule,
Class dataClass,
Spliterator> spliterator,
IssuesHandler issuesHandler,
ProgressController controller) {
final IssuesDetector detector =
createIssuesDetector(project, snapshot, configuredRule, dataClass);
apply(detector, spliterator, issuesHandler, controller);
}
/**
* Checks all possible rules enabled in a profile and matching a data source.
*
* WARNING: A enabled rule for which no appropriate factory is
* declared in this catalog won't be checked.
*
* @param The data type.
* @param project The project for which the detector is created.
* @param snapshot The snapshot for which the detector is created.
* @param profile The profile.
* @param source The data source.
* @param issuesHandler The issues handler that will collect issues.
* @param controller The progress controller.
*/
public default void apply(String project,
String snapshot,
Profile profile,
DataSource source,
IssuesHandler issuesHandler,
ProgressController controller) {
for (final IssuesDetector.Factory factory : getFactories(source.getDataClass())) {
final Set rules = new HashSet<>(profile.getEnabledRules());
rules.retainAll(factory.getSupportedRules());
if (!rules.isEmpty()) {
final Set crules = new HashSet<>();
for (final Rule rule : rules) {
final ConfiguredRule crule = profile.getConfiguredRule(rule);
crules.add(crule);
}
final IssuesDetector detector =
factory.create(project,
snapshot,
crules);
apply(detector,
source.getSpliterator(),
issuesHandler,
controller);
}
}
}
/**
* Checks all data associated to a project with available enabled rules.
*
* @param project The project.
* @param issuesHandler The issues handler that will collect issues.
* @param controller The progress controller.
*/
public default void apply(Project project,
IssuesHandler issuesHandler,
ProgressController controller) {
for (final DataSource> source : project.getDataSources()) {
apply(project.getName(),
project.getProfile().orElseThrow().getName(),
project.getProfile().orElseThrow(),
source,
issuesHandler,
controller);
}
}
/**
* Applies an IssuesDetector to data provided by a Spliterator.
*
* @param The data type.
* @param detector The detector.
* @param spliterator The data spliterator.
* @param issuesHandler The issues handler that will collect issues.
* @param controller The progress controller.
*/
public static void apply(IssuesDetector detector,
Spliterator> spliterator,
IssuesHandler issuesHandler,
ProgressController controller) {
Checks.isNotNull(detector, "detector");
Checks.isNotNull(spliterator, "spliterator");
Checks.isNotNull(issuesHandler, "issuesHandler");
Checks.isNotNull(controller, "controller");
final ProgressSupplier progress = new ProgressSupplier(controller);
progress.reset(spliterator.estimateSize(),
IssuesDetector.toString(detector));
final Consumer> consumer =
ld -> detector.analyze(ld.getObject(),
ld.getLocation(),
issuesHandler);
boolean next = true;
while (next) {
next = spliterator.tryAdvance(consumer);
next = next && !controller.isCancelled();
progress.incrementValue();
}
}
}