workcraft/workcraft

View on GitHub
workcraft/DfsPlugin/src/org/workcraft/plugins/dfs/tools/DfsSimulationTool.java

Summary

Maintainability
C
1 day
Test Coverage
package org.workcraft.plugins.dfs.tools;

import org.workcraft.dom.Node;
import org.workcraft.dom.math.MathNode;
import org.workcraft.dom.visual.HitMan;
import org.workcraft.dom.visual.VisualModel;
import org.workcraft.dom.visual.VisualTransformableNode;
import org.workcraft.gui.events.GraphEditorMouseEvent;
import org.workcraft.gui.tools.Decorator;
import org.workcraft.gui.tools.GraphEditor;
import org.workcraft.plugins.builtin.settings.SimulationDecorationSettings;
import org.workcraft.plugins.dfs.BinaryRegister.Marking;
import org.workcraft.plugins.dfs.*;
import org.workcraft.plugins.dfs.decorations.*;
import org.workcraft.plugins.dfs.stg.*;
import org.workcraft.plugins.petri.Place;
import org.workcraft.plugins.petri.Transition;
import org.workcraft.plugins.petri.VisualPlace;
import org.workcraft.plugins.stg.Stg;
import org.workcraft.plugins.stg.VisualSignalTransition;
import org.workcraft.plugins.stg.tools.StgSimulationTool;
import org.workcraft.utils.Hierarchy;
import org.workcraft.utils.WorkspaceUtils;
import org.workcraft.workspace.WorkspaceEntry;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

public class DfsSimulationTool extends StgSimulationTool {
    private DfsToStgConverter converter;

    @Override
    public void deactivated(GraphEditor editor) {
        super.deactivated(editor);
        this.converter = null;
    }

    @Override
    public void generateUnderlyingModel(WorkspaceEntry we) {
        converter = new DfsToStgConverter(WorkspaceUtils.getAs(we, VisualDfs.class));
    }

    @Override
    public Stg getUnderlyingModel() {
        return converter.getStgModel().getMathModel();
    }

    @Override
    public VisualModel getUnderlyingVisualModel() {
        return converter.getStgModel();
    }

    private VisualPlace getUnderlyingVisualPlace(Place place) {
        VisualPlace result = null;
        for (VisualPlace vp: Hierarchy.getDescendantsOfType(converter.getStgModel().getRoot(), VisualPlace.class)) {
            if (vp.getReferencedComponent() == place) {
                result = vp;
                break;
            }
        }
        return result;
    }

    private void copyTokenColor(VisualAbstractRegister r, Node nodeM) {
        VisualPlace vp = getUnderlyingVisualPlace((Place) nodeM);
        if (vp != null) {
            r.setTokenColor(vp.getTokenColor());
        }
    }

    @Override
    public void applySavedState(final GraphEditor editor) {
        if ((savedState == null) || savedState.isEmpty()) {
            return;
        }
        editor.getWorkspaceEntry().saveMemento();
        VisualDfs dfs = (VisualDfs) editor.getModel();
        for (VisualLogic node : dfs.getVisualLogics()) {
            String c1Ref = DfsToStgConverter.getLogicStgNodeReference(dfs.getMathReference(node), true);
            Node c1Node = getUnderlyingModel().getNodeByReference(c1Ref);
            if ((c1Node instanceof Place) && savedState.containsKey(c1Node)) {
                boolean computed = savedState.get(c1Node) > 0;
                node.getReferencedComponent().setComputed(computed);
            }
        }
        for (VisualRegister node : dfs.getVisualRegisters()) {
            String m1Ref = DfsToStgConverter.getRegisterStgNodeReference(dfs.getMathReference(node), true);
            Node m1Node = getUnderlyingModel().getNodeByReference(m1Ref);
            if ((m1Node instanceof Place) && savedState.containsKey(m1Node)) {
                boolean marked = savedState.get(m1Node) > 0;
                node.getReferencedComponent().setMarked(marked);
                copyTokenColor(node, m1Node);
            }
        }
        for (VisualCounterflowLogic node : dfs.getVisualCounterflowLogics()) {
            String fwC1Ref = DfsToStgConverter.getCounterflowLogicStgNodeReference(dfs.getMathReference(node), true, true);
            Node fwC1Node = getUnderlyingModel().getNodeByReference(fwC1Ref);
            if ((fwC1Node instanceof Place) && savedState.containsKey(fwC1Node)) {
                boolean forwardComputed = savedState.get(fwC1Node) > 0;
                node.getReferencedComponent().setForwardComputed(forwardComputed);
            }
            String bwC1Ref = DfsToStgConverter.getCounterflowLogicStgNodeReference(dfs.getMathReference(node), false, true);
            Node bwC1Node = getUnderlyingModel().getNodeByReference(bwC1Ref);
            if ((bwC1Node instanceof Place) && savedState.containsKey(bwC1Node)) {
                boolean backwardComputed = savedState.get(bwC1Node) > 0;
                node.getReferencedComponent().setBackwardComputed(backwardComputed);
            }
        }
        for (VisualCounterflowRegister node : dfs.getVisualCounterflowRegisters()) {
            String orM1Ref = DfsToStgConverter.getCounterflowRegisterStgNodeReference(dfs.getMathReference(node), true, true);
            Node orM1Node = getUnderlyingModel().getNodeByReference(orM1Ref);
            if ((orM1Node instanceof Place) && savedState.containsKey(orM1Node)) {
                boolean orMarked = savedState.get(orM1Node) > 0;
                node.getReferencedComponent().setOrMarked(orMarked);
                copyTokenColor(node, orM1Node);
            }
            String andM1Ref = DfsToStgConverter.getCounterflowRegisterStgNodeReference(dfs.getMathReference(node), false, true);
            Node andM1Node = getUnderlyingModel().getNodeByReference(andM1Ref);
            if ((andM1Node instanceof Place) && savedState.containsKey(andM1Node)) {
                boolean andMarked = savedState.get(andM1Node) > 0;
                node.getReferencedComponent().setAndMarked(andMarked);
                copyTokenColor(node, andM1Node);
            }
        }
        Collection<VisualBinaryRegister> binaryRegisters = new HashSet<>();
        binaryRegisters.addAll(dfs.getVisualControlRegisters());
        binaryRegisters.addAll(dfs.getVisualPushRegisters());
        binaryRegisters.addAll(dfs.getVisualPopRegisters());
        for (VisualBinaryRegister node :  binaryRegisters) {
            node.getReferencedComponent().setMarking(Marking.EMPTY);
            String trueM1Ref = DfsToStgConverter.getBinaryRegisterStgNodeReference(dfs.getMathReference(node), true, true);
            Node trueM1Node = getUnderlyingModel().getNodeByReference(trueM1Ref);
            if ((trueM1Node instanceof Place) && savedState.containsKey(trueM1Node)) {
                if (savedState.get(trueM1Node) > 0) {
                    node.getReferencedComponent().setMarking(Marking.TRUE_TOKEN);
                }
                copyTokenColor(node, trueM1Node);
            }
            String falseM1Ref = DfsToStgConverter.getBinaryRegisterStgNodeReference(dfs.getMathReference(node), false, true);
            Node falseM1Node = getUnderlyingModel().getNodeByReference(falseM1Ref);
            if ((falseM1Node instanceof Place) && savedState.containsKey(falseM1Node)) {
                if (savedState.get(falseM1Node) > 0) {
                    node.getReferencedComponent().setMarking(Marking.FALSE_TOKEN);
                }
                copyTokenColor(node, falseM1Node);
            }
        }
    }

    @Override
    public void mousePressed(GraphEditorMouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON1) {
            VisualModel model = e.getModel();
            Node deepestNode = HitMan.hitDeepest(e.getPosition(), model.getRoot(),
                    node -> getExcitedTransitionOfNode(node) != null);

            Transition transition = null;
            if (deepestNode instanceof VisualTransformableNode) {
                Point2D nodespacePosition = model.getNodeSpacePosition(e.getPosition(), (VisualTransformableNode) deepestNode);
                if (deepestNode instanceof VisualCounterflowLogic) {
                    CounterflowLogicStg nodeStg = converter.getCounterflowLogicStg((VisualCounterflowLogic) deepestNode);
                    if (nodespacePosition.getY() < 0) {
                        transition = getExcitedTransitionOfCollection(nodeStg.getForwardTransitions());
                    } else {
                        transition = getExcitedTransitionOfCollection(nodeStg.getBackwardTransitions());
                    }
                } else if (deepestNode instanceof VisualCounterflowRegister) {
                    CounterflowRegisterStg nodeStg = converter.getCounterflowRegisterStg((VisualCounterflowRegister) deepestNode);
                    if (nodespacePosition.getY() < 0) {
                        transition = getExcitedTransitionOfCollection(nodeStg.getOrTransitions());
                    } else {
                        transition = getExcitedTransitionOfCollection(nodeStg.getAndTransitions());
                    }
                } else if (deepestNode instanceof VisualControlRegister) {
                    BinaryRegisterStg nodeStg = converter.getControlRegisterStg((VisualControlRegister) deepestNode);
                    if (nodespacePosition.getY() < 0) {
                        transition = getExcitedTransitionOfCollection(nodeStg.getTrueTransitions());
                    } else {
                        transition = getExcitedTransitionOfCollection(nodeStg.getFalseTransitions());
                    }
                } else if (deepestNode instanceof VisualPushRegister) {
                    BinaryRegisterStg nodeStg = converter.getPushRegisterStg((VisualPushRegister) deepestNode);
                    if (nodespacePosition.getY() < 0) {
                        transition = getExcitedTransitionOfCollection(nodeStg.getTrueTransitions());
                    } else {
                        transition = getExcitedTransitionOfCollection(nodeStg.getFalseTransitions());
                    }
                } else if (deepestNode instanceof VisualPopRegister) {
                    BinaryRegisterStg nodeStg = converter.getPopRegisterStg((VisualPopRegister) deepestNode);
                    if (nodespacePosition.getY() < 0) {
                        transition = getExcitedTransitionOfCollection(nodeStg.getTrueTransitions());
                    } else {
                        transition = getExcitedTransitionOfCollection(nodeStg.getFalseTransitions());
                    }
                }
            }

            if (transition == null) {
                transition = getExcitedTransitionOfNode(deepestNode);
            }

            if (transition != null) {
                executeUnderlyingNode(e.getEditor(), transition);
            }
        }
    }

    @Override
    public String getHintText(final GraphEditor editor) {
        return "Click on a highlighted node to progress.";
    }

    @Override
    public Decorator getDecorator(final GraphEditor editor) {
        return node -> {
            MathNode underlyingNode = getCurrentUnderlyingNode();
            final boolean isExcited = getExcitedTransitionOfNode(node) != null;
            final boolean isSuggested = isExcited && converter.isRelated(node, underlyingNode);

            if (node instanceof VisualLogic) {
                final LogicStg nodeStg = converter.getLogicStg((VisualLogic) node);

                return new LogicDecoration() {
                    @Override
                    public Color getColorisation() {
                        return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
                    }

                    @Override
                    public Color getBackground() {
                        return isSuggested ? SimulationDecorationSettings.getSuggestedComponentColor() : null;
                    }

                    @Override
                    public boolean isComputed() {
                        return nodeStg.c0.getReferencedComponent().getTokens() == 0;
                    }
                };
            }

            if (node instanceof VisualRegister) {
                final RegisterStg nodeStg = converter.getRegisterStg((VisualRegister) node);

                return new RegisterDecoration() {
                    @Override
                    public Color getColorisation() {
                        return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
                    }

                    @Override
                    public Color getBackground() {
                        return isSuggested ? SimulationDecorationSettings.getSuggestedComponentColor() : null;
                    }

                    @Override
                    public boolean isMarked() {
                        return nodeStg.m0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isExcited() {
                        return getExcitedTransitionOfCollection(Arrays.asList(nodeStg.mR, nodeStg.mF)) != null;
                    }

                    @Override
                    public Color getTokenColor() {
                        return nodeStg.m1.getTokenColor();
                    }
                };
            }

            if (node instanceof VisualCounterflowLogic) {
                final CounterflowLogicStg nodeStg = converter.getCounterflowLogicStg((VisualCounterflowLogic) node);

                return new CounterflowLogicDecoration() {
                    @Override
                    public Color getColorisation() {
                        return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
                    }

                    @Override
                    public Color getBackground() {
                        return isSuggested ? SimulationDecorationSettings.getSuggestedComponentColor() : null;
                    }

                    @Override
                    public boolean isForwardComputed() {
                        return nodeStg.fwC0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isBackwardComputed() {
                        return nodeStg.bwC0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isForwardComputedExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getForwardTransitions()) != null;
                    }

                    @Override
                    public boolean isBackwardComputedExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getBackwardTransitions()) != null;
                    }
                };
            }

            if (node instanceof VisualCounterflowRegister) {
                final CounterflowRegisterStg nodeStg = converter.getCounterflowRegisterStg((VisualCounterflowRegister) node);

                return new CounterflowRegisterDecoration() {
                    @Override
                    public Color getColorisation() {
                        return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
                    }

                    @Override
                    public Color getBackground() {
                        return isSuggested ? SimulationDecorationSettings.getSuggestedComponentColor() : null;
                    }

                    @Override
                    public boolean isForwardExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getForwardTransitions()) != null;
                    }

                    @Override
                    public boolean isBackwardExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getBackwardTransitions()) != null;
                    }

                    @Override
                    public boolean isOrMarked() {
                        return nodeStg.orM0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isAndMarked() {
                        return nodeStg.andM0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isOrExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getOrTransitions()) != null;
                    }

                    @Override
                    public boolean isAndExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getAndTransitions()) != null;
                    }

                    @Override
                    public Color getTokenColor() {
                        return nodeStg.orM1.getTokenColor();
                    }
                };
            }

            if ((node instanceof VisualControlRegister) || (node instanceof VisualPushRegister) || (node instanceof VisualPopRegister)) {
                BinaryRegisterStg tmpStg = null;
                if (node instanceof VisualControlRegister) {
                    tmpStg = converter.getControlRegisterStg((VisualControlRegister) node);
                }
                if (node instanceof VisualPushRegister) {
                    tmpStg = converter.getPushRegisterStg((VisualPushRegister) node);
                }
                if (node instanceof VisualPopRegister) {
                    tmpStg = converter.getPopRegisterStg((VisualPopRegister) node);
                }
                final BinaryRegisterStg nodeStg = tmpStg;

                return new BinaryRegisterDecoration() {
                    @Override
                    public Color getColorisation() {
                        return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
                    }

                    @Override
                    public Color getBackground() {
                        return isSuggested ? SimulationDecorationSettings.getSuggestedComponentColor() : null;
                    }

                    @Override
                    public boolean isTrueMarked() {
                        return nodeStg.tM0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isTrueExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getTrueTransitions()) != null;
                    }

                    @Override
                    public boolean isFalseMarked() {
                        return nodeStg.fM0.getReferencedComponent().getTokens() == 0;
                    }

                    @Override
                    public boolean isFalseExcited() {
                        return getExcitedTransitionOfCollection(nodeStg.getFalseTransitions()) != null;
                    }

                    @Override
                    public Color getTokenColor() {
                        return nodeStg.m1.getTokenColor();
                    }
                };
            }

            return null;
        };
    }

    private Transition getExcitedTransitionOfNode(Node node) {
        List<VisualSignalTransition> ts = null;
        if (node != null) {
            if (node instanceof VisualLogic) {
                ts = converter.getLogicStg((VisualLogic) node).getAllTransitions();
            } else if (node instanceof VisualRegister) {
                ts = converter.getRegisterStg((VisualRegister) node).getAllTransitions();
            } else if (node instanceof VisualCounterflowLogic) {
                ts = converter.getCounterflowLogicStg((VisualCounterflowLogic) node).getAllTransitions();
            } else if (node instanceof VisualCounterflowRegister) {
                ts = converter.getCounterflowRegisterStg((VisualCounterflowRegister) node).getAllTransitions();
            } else if (node instanceof VisualControlRegister) {
                ts = converter.getControlRegisterStg((VisualControlRegister) node).getAllTransitions();
            } else if (node instanceof VisualPushRegister) {
                ts = converter.getPushRegisterStg((VisualPushRegister) node).getAllTransitions();
            } else if (node instanceof VisualPopRegister) {
                ts = converter.getPopRegisterStg((VisualPopRegister) node).getAllTransitions();
            }
        }
        return getExcitedTransitionOfCollection(ts);
    }

    private Transition getExcitedTransitionOfCollection(List<VisualSignalTransition> ts) {
        if (ts != null) {
            for (VisualSignalTransition t: ts) {
                if (t == null) continue;
                Transition transition = t.getReferencedComponent();
                if (isEnabledUnderlyingNode(transition)) {
                    return transition;
                }
            }
        }
        return null;
    }

}