package ql.semantics;
import java.util.*;
/**
* Created by bore on 17/02/15.
*/
public class QuestionDependencies
{
private final Map<String, Set<String>> dependencies;
private Identifiers cyclicIds;
public QuestionDependencies()
{
this.dependencies = new HashMap<>();
}
public void addQuestion(String id)
{
if (!(this.dependencies.containsKey(id)))
{
this.dependencies.put(id, new HashSet<>());
}
}
public void addDependency(String q, String dep)
{
assert this.dependencies.containsKey(q);
this.dependencies.get(q).add(dep);
}
public Identifiers getCycleIds()
{
return this.cyclicIds;
}
public boolean containsCycle()
{
return this.findCycles();
}
private boolean findCycles()
{
this.cyclicIds = new Identifiers();
for (String id : this.dependencies.keySet())
{
Stack<String> path = new Stack<>();
path.add(id);
if (this.searchNeighboursForCycles(path))
{
return true;
}
}
return false;
}
private boolean searchNeighboursForCycles(Stack<String> path)
{
Set<String> neighbours = this.getNeighbours(path.lastElement());
for (String n : neighbours)
{
if (this.isNeighbourFormingCycle(path, n))
{
return true;
}
path.push(n);
if (this.searchNeighboursForCycles(path))
{
return true;
}
path.pop();
}
return false;
}
private boolean isNeighbourFormingCycle(Stack<String> path, String n)
{
String firstElement = path.firstElement();
if (firstElement.equals(n))
{
this.cyclicIds.addAll(path);
return true;
}
return false;
}
private Set<String> getNeighbours(String id)
{
if (this.isIdentUndeclared(id))
{
return new HashSet<>();
}
return this.dependencies.get(id);
}
private boolean isIdentUndeclared(String id)
{
return !this.dependencies.containsKey(id);
}
}