workcraft/SonPlugin/src/org/workcraft/plugins/son/tasks/TimeConsistencyTask.java
package org.workcraft.plugins.son.tasks;
import org.apache.log4j.Logger;
import org.workcraft.dom.Node;
import org.workcraft.plugins.son.SON;
import org.workcraft.plugins.son.SONSettings;
import org.workcraft.plugins.son.TimeConsistencySettings;
import org.workcraft.plugins.son.algorithm.ConsistencyAlg;
import org.workcraft.plugins.son.algorithm.DFSEstimationAlg;
import org.workcraft.plugins.son.algorithm.TimeAlg;
import org.workcraft.plugins.son.elements.ChannelPlace;
import org.workcraft.plugins.son.elements.Time;
import org.workcraft.plugins.son.exception.AlternativeStructureException;
import org.workcraft.plugins.son.exception.TimeEstimationException;
import org.workcraft.plugins.son.exception.TimeOutOfBoundsException;
import org.workcraft.plugins.son.gui.TimeConsistencyDialog.Granularity;
import org.workcraft.plugins.son.util.Interval;
import org.workcraft.tasks.ProgressMonitor;
import org.workcraft.tasks.Result;
import org.workcraft.tasks.Task;
import org.workcraft.utils.WorkspaceUtils;
import org.workcraft.workspace.WorkspaceEntry;
import java.awt.*;
import java.util.*;
public class TimeConsistencyTask implements Task<VerificationResult> {
private final SON net;
private final Logger logger = Logger.getLogger(this.getClass().getName());
private ConsistencyAlg consistencyAlg;
private DFSEstimationAlg estimationAlg;
private final TimeConsistencySettings settings;
private static final Color causalColor = new Color(225, 90, 70);
private static final Color inconsistencyColor = new Color(250, 210, 80);
private int totalErrNum = 0;
public TimeConsistencyTask(WorkspaceEntry we, TimeConsistencySettings settings) {
this.settings = settings;
net = WorkspaceUtils.getAs(we, SON.class);
initialise();
}
@Override
public Result<? extends VerificationResult> run(ProgressMonitor<? super VerificationResult> monitor) {
Collection<Node> checkList = new ArrayList<>();
Map<Node, Boolean[]> timeInfoMap = new HashMap<>();
Collection<Node> specifyNodes = new ArrayList<>();
Collection<Node> unspecifyNodes = new ArrayList<>();
Collection<Node> partialNodes = new ArrayList<>();
Map<Node, Boolean[]> partialNodesMap = new HashMap<>();
Collection<Node> outOfBoundNodes = new ArrayList<>();
Collection<Node> inconsistencyNodes = new ArrayList<>();
Collection<Node> causalInconsistencyNodes = new ArrayList<>();
infoMsg("-------------------------Time Consistency Checking Result-------------------------");
if (settings.getTabIndex() == 0) {
infoMsg("Initialising selected scenario...");
checkList = consistencyAlg.getScenario().getNodes(net);
infoMsg("Nodes = " + checkList.size() + '\n');
} else if (settings.getTabIndex() == 1) {
// node info
infoMsg("Initialising selected components...");
checkList = settings.getSeletedNodes();
infoMsg("Selected nodes = " + checkList.size() + '\n');
}
// create partial node map
// s[0] = start
// s[1] = duration
// s[2] = end
infoMsg("Create time information map...");
timeInfoMap = createTimeInfoMap(consistencyAlg.getScenario().getNodes(net));
if (settings.getGranularity() == Granularity.YEAR_YEAR) {
infoMsg("Time granularity: T:year D:year");
} else if (settings.getGranularity() == Granularity.HOUR_MINS) {
infoMsg("Time granularity: T:24 hour clock D:minutes");
infoMsg("Running time granularity checking task...");
for (Node node : checkList) {
ArrayList<String> result = consistencyAlg.granularityHourMinsTask(node);
if (!result.isEmpty()) {
outOfBoundNodes.add(node);
infoMsg("Node:" + net.getNodeReference(node));
for (String str : result) {
totalErrNum++;
errMsg(str);
}
}
}
}
infoMsg("Remove invalid time granularity nodes from checking list...");
checkList.removeAll(outOfBoundNodes);
// specifiedNodes: place nodes and transition nodes with specified
// start,
// duration and end; channel place with specified start and end.
// unspecifiedNodes: nodes with unspecified start and end
// partialNodes: start or end is unspecified
infoMsg("--------------------------------------------------");
infoMsg("Running time information checking task...");
for (Node node : checkList) {
Time t = (Time) node;
if (!t.getStartTime().isSpecified() && !t.getEndTime().isSpecified()) {
unspecifyNodes.add(t);
} else if (t.getStartTime().isSpecified() && t.getEndTime().isSpecified()) {
if (t instanceof ChannelPlace) {
specifyNodes.add(t);
} else {
if (t.getDuration().isSpecified()) {
specifyNodes.add(t);
} else {
partialNodes.add(node);
}
}
} else {
partialNodes.add(node);
}
}
infoMsg("Node with complete time information: " + specifyNodes.size());
infoMsg("Node with partial time information: " + partialNodes.size());
infoMsg("Node with empty time information: " + unspecifyNodes.size());
if ((settings.getTabIndex() == 0) && settings.isCausalConsistency()) {
infoMsg("--------------------------------------------------");
infoMsg("Set estimated time interval for nodes with partial time infomation...");
infoMsg("Default duration = " + settings.getDefaultDuration().toString());
infoMsg("Create partial time information map...");
partialNodesMap = createTimeInfoMap(partialNodes);
Map<Node, ArrayList<String>> estimationResult = timeEstimationTask(partialNodesMap);
for (Node node : estimationResult.keySet()) {
Time n = (Time) node;
infoMsg("Node:" + net.getNodeReference(node));
String value = "";
Boolean[] s = partialNodesMap.get(node);
if (!s[0] && n.getStartTime().isSpecified()) {
value = "Estimated start = " + ((Time) node).getStartTime() + ' ';
}
if (!s[1] && n.getDuration().isSpecified()) {
value += "Estimated duration = " + ((Time) node).getDuration() + ' ';
}
if (!s[2] && n.getEndTime().isSpecified()) {
value += "Estimated finish = " + ((Time) node).getEndTime();
}
if (!value.isEmpty()) {
infoMsg("-" + value);
}
ArrayList<String> err = estimationResult.get(node);
if (!err.isEmpty()) {
for (String str : err) {
infoMsg("-" + str);
}
} else {
specifyNodes.add(node);
}
}
}
infoMsg("Node with complete time information: " + specifyNodes.size());
infoMsg("--------------------------------------------------");
infoMsg("Running ON consistency checking task...");
Map<Node, ArrayList<String>> onResult = consistencyAlg.onConsistency(specifyNodes);
for (Node node : onResult.keySet()) {
infoMsg("Node:" + net.getNodeReference(node));
Time n = (Time) node;
infoMsg("-start=" + (n.getStartTime()) + " finish=" + (n.getEndTime()) + " duration=" + (n.getDuration()));
ArrayList<String> err = onResult.get(node);
for (String str : err) {
errMsg(str);
totalErrNum++;
}
if (!err.isEmpty()) {
inconsistencyNodes.add(node);
}
}
infoMsg("--------------------------------------------------");
infoMsg("Running CSON consistency checking task...");
Map<Node, ArrayList<String>> csonResult = consistencyAlg.csonConsistency(specifyNodes);
for (Node node : csonResult.keySet()) {
infoMsg("Node:" + net.getNodeReference(node));
Time n = (Time) node;
infoMsg("-start=" + (n.getStartTime()) + " finish=" + (n.getEndTime()) + " duration=" + (n.getDuration()));
ArrayList<String> err = csonResult.get(node);
for (String str : err) {
errMsg(str);
totalErrNum++;
}
if (!err.isEmpty()) {
inconsistencyNodes.add(node);
}
}
infoMsg("--------------------------------------------------");
infoMsg("Running BSON consistency checking task...");
Map<HashSet<Node>, ArrayList<String>> bsonResult = consistencyAlg.bsonConsistency(specifyNodes);
for (HashSet<Node> nodes : bsonResult.keySet()) {
infoMsg("Behavioural causal nodes:" + net.toString(nodes));
ArrayList<String> err = bsonResult.get(nodes);
for (String str : err) {
errMsg(str);
totalErrNum++;
}
if (!err.isEmpty()) {
inconsistencyNodes.addAll(nodes);
}
}
inconsistencyHighlight(settings.getInconsistencyHighlight(), inconsistencyNodes);
unspecifyHighlight(settings.getUnspecifyHighlight(), unspecifyNodes);
causalHighlight(settings.isCausalHighlight(), causalInconsistencyNodes);
complete(timeInfoMap);
logger.info("\n\nVerification-Result : " + totalErrNum + " Error(s).");
return Result.success();
}
private Map<Node, Boolean[]> createTimeInfoMap(Collection<Node> nodes) {
Map<Node, Boolean[]> result = new HashMap<>();
for (Node node : nodes) {
Time t = (Time) node;
Boolean[] s = new Boolean[3];
if (t.getStartTime().isSpecified()) {
s[0] = true;
} else {
s[0] = false;
}
if (t.getDuration().isSpecified()) {
s[1] = true;
} else {
s[1] = false;
}
if (t.getEndTime().isSpecified()) {
s[2] = true;
} else {
s[2] = false;
}
result.put(node, s);
}
return result;
}
private Map<Node, ArrayList<String>> timeEstimationTask(Map<Node, Boolean[]> map) {
Map<Node, ArrayList<String>> result = new HashMap<>();
for (Node node : map.keySet()) {
Boolean[] s = map.get(node);
ArrayList<String> subStr = new ArrayList<>();
if (!s[0]) {
try {
estimationAlg.estimateStartTime(node);
} catch (TimeOutOfBoundsException | TimeEstimationException e1) {
subStr.add(e1.getMessage());
}
}
if (!s[1]) {
((Time) node).setDuration(settings.getDefaultDuration());
}
if (!s[2]) {
try {
estimationAlg.estimateEndTime(node);
} catch (TimeOutOfBoundsException | TimeEstimationException e1) {
subStr.add(e1.getMessage());
}
}
result.put(node, subStr);
}
return result;
}
public void initialise() {
try {
consistencyAlg = new ConsistencyAlg(net, settings.getDefaultDuration(), settings.getGranularity(),
settings.getSeletedScenario());
estimationAlg = new DFSEstimationAlg(net, settings.getDefaultDuration(), settings.getGranularity(),
settings.getSeletedScenario());
} catch (AlternativeStructureException e) {
errMsg(e.getMessage());
return;
}
consistencyAlg.prepare();
TimeAlg.removeProperties(net);
TimeAlg.setProperties(net);
}
protected void complete(Map<Node, Boolean[]> map) {
if (!SONSettings.getTimeVisibility()) {
TimeAlg.removeProperties(net);
}
for (Node node : map.keySet()) {
if (!map.get(node)[1]) {
((Time) node).setDuration(new Interval());
}
}
consistencyAlg.complete();
}
private void inconsistencyHighlight(boolean b, Collection<Node> nodes) {
if (b) {
for (Node node : nodes) {
net.setForegroundColor(node, inconsistencyColor);
}
}
}
private void unspecifyHighlight(boolean b, Collection<Node> nodes) {
if (b) {
for (Node node : nodes) {
net.setForegroundColor(node, new Color(204, 204, 255));
}
}
}
private void causalHighlight(boolean b, Collection<Node> nodes) {
if (b) {
for (Node node : nodes) {
net.setForegroundColor(node, causalColor);
}
}
}
public void infoMsg(String msg) {
logger.info(msg);
}
public void errMsg(String msg) {
logger.info("[ERROR] " + msg);
}
}