//This product is provided under the terms of EPL (Eclipse Public License)
//version 1.0.
//
//The full license text can be read from: http://www.eclipse.org/org/documents/epl-v10.php
package org.dtangler.core.ruleanalysis;
import java.util.List;
import java.util.Set;
import org.dtangler.core.analysis.DependencyAnalyzer;
import org.dtangler.core.dependencies.Dependable;
import org.dtangler.core.dependencies.Dependencies;
import org.dtangler.core.dependencies.Dependency;
public class ForbiddenDependencyFinder extends DependencyAnalyzer {
private final RuleFilter ruleFilter;
public ForbiddenDependencyFinder(List<Rule> rules) {
this.ruleFilter = new RuleFilter(rules);
}
public boolean isValidResult() {
return getViolations().isEmpty();
}
@Override
public final void doAnalyze(Dependencies dependencies) {
Set<Dependable> items = dependencies.getAllItems();
for (Dependable dep : items) {
Set<Dependable> dependees = dependencies.getDependencyGraph(
dep.getScope()).getDependencies(dep);
analyze(dep, dependees, dependencies);
}
}
protected void analyze(Dependable dependant, Set<Dependable> dependees,
Dependencies dependencies) {
List<Rule> rules = ruleFilter.getRulesForDependant(dependant);
rules.addAll(ruleFilter.getParentRulesForDependant(dependant,
dependencies));
if (rules.size() == 0)
return;
for (Rule rule : rules) {
checkRule(dependant, dependees, rule, dependencies);
}
}
private void checkRule(Dependable dependant, Set<Dependable> dependees,
Rule rule, Dependencies dependencies) {
for (Dependable dependee : dependees) {
Set<Dependable> parents = dependencies
.getParentsFromAllScopes(dependee);
if (!isRuleApplicable(rule, dependee, parents))
continue;
// check for an allowing rule that overrides the forbidden rule
if (ruleFilter.isDependencyAllowedByRule(dependant, dependee))
continue;
addViolation(dependant, dependee, rule);
}
}
private boolean isRuleApplicable(Rule rule, Dependable dependee,
Set<Dependable> parents) {
if (rule.getType().equals(Rule.Type.canDepend))
return false;
if (rule.appliesToRightSide(dependee))
return true;
for (Dependable parent : parents) {
if (rule.appliesToRightSide(parent))
return true;
}
return false;
}
private void addViolation(Dependable dependant, Dependable dependee,
Rule violatedRule) {
Dependency dependency = new Dependency(dependant, dependee);
addViolation(dependency, new RuleViolation(dependency, violatedRule));
}
}