package nl.uva.se.ql.typechecking; import java.util.ArrayList; import java.util.List; import java.util.Set; import nl.uva.se.ql.ast.statement.Question; import nl.uva.se.ql.typechecking.error.CyclicDependency; import nl.uva.se.ql.typechecking.error.ErrorList; public class CyclicDependencyChecker { private DependencyTable dependencies; private ErrorList errors; private CyclicDependencyChecker(DependencyTable dependencies) { this.dependencies = dependencies; errors = new ErrorList(); } public static ErrorList check(DependencyTable dependencies) { CyclicDependencyChecker checker = new CyclicDependencyChecker( dependencies); checker.findCycles(); return checker.errors; } private void findCycles() { for (Question q : dependencies) { checkDependenciesFor(q); } } private void checkDependenciesFor(Question question) { Set<Question> dpc = dependencies.getDependenciesFor(question); for (Question dependant : dpc) { if (dependant.equals(question)) { errors.addError(new CyclicDependency(question.getLineNumber(), question.getOffset())); } checkAllPaths(question, dependencies.getDependenciesFor(dependant), new ArrayList<Question>()); } } private void checkAllPaths(Question question, Set<Question> dependants, List<Question> visited) { for (Question q : dependants) { if (!visited.contains(q)) { visited.add(q); if (q.equals(question)) { errors.addError(new CyclicDependency(question .getLineNumber(), question.getOffset())); } checkAllPaths(question, dependencies.getDependenciesFor(q), visited); } } } }