de.uni.freiburg.iig.telematik.sepia.replay.ReplayCallable Maven / Gradle / Ivy
Show all versions of SEPIA Show documentation
package de.uni.freiburg.iig.telematik.sepia.replay;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.uni.freiburg.iig.telematik.sepia.exception.PNException;
import de.uni.freiburg.iig.telematik.sepia.petrinet.abstr.AbstractFlowRelation;
import de.uni.freiburg.iig.telematik.sepia.petrinet.abstr.AbstractMarking;
import de.uni.freiburg.iig.telematik.sepia.petrinet.abstr.AbstractPlace;
import de.uni.freiburg.iig.telematik.sepia.petrinet.abstr.AbstractTransition;
import de.uni.freiburg.iig.telematik.sepia.petrinet.properties.threaded.AbstractPNPropertyCheckerCallable;
import de.uni.freiburg.iig.telematik.sepia.util.PNUtils;
import de.uni.freiburg.iig.telematik.sewol.log.LogEntry;
import de.uni.freiburg.iig.telematik.sewol.log.LogTrace;
public class ReplayCallable< P extends AbstractPlace,
T extends AbstractTransition,
F extends AbstractFlowRelation,
M extends AbstractMarking,
S extends Object,
E extends LogEntry> extends AbstractPNPropertyCheckerCallable
> {
public ReplayCallable(ReplayCallableGenerator
generator) {
super(generator);
}
@SuppressWarnings("unchecked")
@Override
protected ReplayCallableGenerator
getGenerator() {
return (ReplayCallableGenerator
) super.getGenerator();
}
@Override
public ReplayResult callRoutine() throws ReplayException, InterruptedException {
if(getGenerator().getLogTraces() == null && getGenerator().getActivitySequences() == null)
throw new ReplayException("Missing replaying input: activity sequences or log traces required");
Collection> fittingTraces = new ArrayList>();
Collection> nonFittingTraces = new ArrayList>();
Collection> fittingSequences = new ArrayList>();
Collection> nonFittingSequences = new ArrayList>();
try {
for (int i = 0; i < getGenerator().getActivitySequences().size(); i++) {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
if (isReplayableRecursive(new ArrayList(), getGenerator().getActivitySequences().get(i))) {
fittingSequences.add(getGenerator().getActivitySequences().get(i));
if (getGenerator().getLogTraces() != null)
fittingTraces.add(getGenerator().getLogTraces().get(i));
} else {
nonFittingSequences.add(getGenerator().getActivitySequences().get(i));
if (getGenerator().getLogTraces() != null)
nonFittingTraces.add(getGenerator().getLogTraces().get(i));
}
}
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
throw new ReplayException("Exception during replay.
Reason: " + e.getMessage(), e);
}
return new ReplayResult(fittingTraces, nonFittingTraces, fittingSequences, nonFittingSequences);
}
@SuppressWarnings("unchecked")
private synchronized boolean isReplayableRecursive(List path, List remainingActivities) throws PNException, InterruptedException{
// System.out.println("REC: " + path + ", " + remainingActivities);
getGenerator().getPetriNet().reset();
for(String pathActivity: path){
getGenerator().getPetriNet().fire(pathActivity);
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
List enabledTransitions = getGenerator().getPetriNet().getEnabledTransitions();
// System.out.println("enabled transitions: " + enabledTransitions);
if(remainingActivities.isEmpty()){
switch(getGenerator().getTerminationCriteria()){
case POSSIBLE_FIRING_SEQUENCE: return true;
case NO_ENABLED_TRANSITIONS: return enabledTransitions.isEmpty();
case ESCAPABLE_WITH_SILENT_TRANSITIONS:
if(enabledTransitions.isEmpty())
return true;
return escapableWithSilentTransitions(enabledTransitions, (M) getGenerator().getPetriNet().getMarking().clone());
}
}
if(enabledTransitions.isEmpty()){
return false;
}
String nextActivity = remainingActivities.get(0);
Set recTransitions = new HashSet();
for(T enabledTransition: enabledTransitions){
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
if(!enabledTransition.isSilent() && getGenerator().getTransitionLabelRelation().get(enabledTransition.getLabel()).equals(nextActivity)){
// System.out.println("Add regular transition: " + enabledTransition);
recTransitions.add(enabledTransition);
}
}
Set enabledSilentTransitions = PNUtils.getSilentTransitions(enabledTransitions);
if(recTransitions.isEmpty() && enabledSilentTransitions.isEmpty()){
return false;
}
for(T enabledSilentTransition: enabledSilentTransitions){
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
recTransitions.add(enabledSilentTransition);
// System.out.println("Add silent transition: " + enabledSilentTransition);
}
for(T recTransition: recTransitions){
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
ArrayList recPath = new ArrayList(path);
ArrayList recRemainingActivities = new ArrayList(remainingActivities);
recPath.add(recTransition.getName());
if(!recTransition.isSilent()){
recRemainingActivities.remove(0);
}
if(isReplayableRecursive(recPath, recRemainingActivities)){
return true;
}
}
return false;
}
@SuppressWarnings("unchecked")
private boolean escapableWithSilentTransitions(List enabledTransitions, M marking) throws PNException, InterruptedException{
if(enabledTransitions.isEmpty())
return true;
Set enabledSilentTransitions = PNUtils.getSilentTransitions(enabledTransitions);
if(enabledSilentTransitions.isEmpty())
return false;
for(T enabledSilentTransition: enabledSilentTransitions){
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
getGenerator().getPetriNet().setMarking((M) marking.clone());
getGenerator().getPetriNet().fire(enabledSilentTransition.getName());
if(escapableWithSilentTransitions(getGenerator().getPetriNet().getEnabledTransitions(), (M) getGenerator().getPetriNet().getMarking().clone())){
return true;
}
}
return false;
}
public enum TerminationCriteria {
POSSIBLE_FIRING_SEQUENCE,
NO_ENABLED_TRANSITIONS,
ESCAPABLE_WITH_SILENT_TRANSITIONS;
}
}