package validator;
import java.util.ArrayList;
import java.util.List;
import util.gdl.grammar.Gdl;
import util.observer.Event;
import util.observer.Observer;
import util.observer.Subject;
import util.statemachine.MachineState;
import util.statemachine.Role;
import util.statemachine.StateMachine;
import util.statemachine.implementation.prover.ProverStateMachine;
import validator.event.ValidatorFailureEvent;
import validator.event.ValidatorSuccessEvent;
import validator.exception.MaxDepthException;
import validator.exception.MonotonicityException;
public final class GdlValidator extends Thread implements Subject
{
private final List<Gdl> description;
private final int maxDepth;
private final int numSimulations;
private final List<Observer> observers;
public GdlValidator(List<Gdl> description, int maxDepth, int numSimulations)
{
this.description = description;
this.maxDepth = maxDepth;
this.numSimulations = numSimulations;
observers = new ArrayList<Observer>();
}
public void addObserver(Observer observer)
{
observers.add(observer);
}
public void notifyObservers(Event event)
{
for (Observer observer : observers)
{
observer.observe(event);
}
}
@Override
public void run()
{
for (int i = 0; i < numSimulations; i++)
{
simulate();
}
}
private void simulate()
{
try
{
StateMachine stateMachine = new ProverStateMachine();
stateMachine.initialize(description);
List<Role> roles = stateMachine.getRoles();
List<Integer> goals = new ArrayList<Integer>();
for (int i = 0; i < roles.size(); i++)
{
goals.add(-1);
}
MachineState state = stateMachine.getInitialState();
for (int depth = 0; !stateMachine.isTerminal(state); depth++)
{
if (depth == maxDepth)
{
throw new MaxDepthException(maxDepth);
}
for (int i = 0; i < roles.size(); i++)
{
int goal = stateMachine.getGoal(state, roles.get(i));
if (goal < goals.get(i))
{
throw new MonotonicityException(roles.get(i));
}
goals.set(i, goal);
}
state = stateMachine.getRandomNextState(state);
}
notifyObservers(new ValidatorSuccessEvent());
}
catch (Exception e)
{
notifyObservers(new ValidatorFailureEvent(e));
}
}
}