workcraft/workcraft

View on GitHub
workcraft/WtgPlugin/src/org/workcraft/plugins/wtg/tools/WtgSimulationTool.java

Summary

Maintainability
A
0 mins
Test Coverage
package org.workcraft.plugins.wtg.tools;

import org.workcraft.dom.Container;
import org.workcraft.dom.Node;
import org.workcraft.dom.math.MathModel;
import org.workcraft.dom.math.MathNode;
import org.workcraft.dom.visual.HitMan;
import org.workcraft.dom.visual.VisualModel;
import org.workcraft.gui.events.GraphEditorMouseEvent;
import org.workcraft.gui.tools.Decoration;
import org.workcraft.gui.tools.Decorator;
import org.workcraft.gui.tools.GraphEditor;
import org.workcraft.plugins.builtin.settings.SimulationDecorationSettings;
import org.workcraft.plugins.dtd.*;
import org.workcraft.plugins.dtd.utils.DtdUtils;
import org.workcraft.plugins.petri.Transition;
import org.workcraft.plugins.stg.NamedTransition;
import org.workcraft.plugins.stg.Stg;
import org.workcraft.plugins.stg.StgPlace;
import org.workcraft.plugins.stg.tools.StgSimulationTool;
import org.workcraft.plugins.wtg.*;
import org.workcraft.plugins.wtg.converter.WtgToStgConverter;
import org.workcraft.plugins.wtg.decorations.StateDecoration;
import org.workcraft.plugins.wtg.decorations.WaveformDecoration;
import org.workcraft.plugins.wtg.utils.VerificationUtils;
import org.workcraft.utils.WorkspaceUtils;
import org.workcraft.workspace.WorkspaceEntry;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;

public class WtgSimulationTool extends StgSimulationTool {

    private WtgToStgConverter converter;

    @Override
    public boolean checkPrerequisites(final GraphEditor editor) {
        final Wtg wtg = (Wtg) editor.getModel().getMathModel();
        return VerificationUtils.checkStructure(wtg) && VerificationUtils.checkNameCollisions(wtg);
    }

    @Override
    public void activated(final GraphEditor editor) {
        super.activated(editor);
        setStatePaneVisibility(true);
    }

    @Override
    public void generateUnderlyingModel(WorkspaceEntry we) {
        final Wtg wtg = WorkspaceUtils.getAs(we, Wtg.class);
        if (VerificationUtils.checkStructure(wtg) && VerificationUtils.checkNameCollisions(wtg)) {
            converter = new WtgToStgConverter(wtg);
        }
    }

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

    @Override
    public VisualModel getUnderlyingVisualModel() {
        return null;
    }

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

            Transition transition = null;
            if (deepestNode instanceof VisualSignal) {
                transition = getExcitedTransitionOfSignal(model, (VisualSignal) deepestNode);
            } else if (deepestNode instanceof VisualEvent) {
                VisualEvent event = (VisualEvent) deepestNode;
                transition = getExcitedTransitionOfEvent(event);
                if (transition == null) {
                    transition = getExcitedTransitionOfSignal(model, event.getVisualSignal());
                }
            }

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

    @Override
    public boolean isContainerExcited(VisualModel model, Container container) {
        if (container instanceof VisualWaveform) {
            Waveform waveform = ((VisualWaveform) container).getReferencedComponent();
            return converter.isActiveWaveform(waveform);
        }
        return false;
    }

    @Override
    public void applySavedState(final GraphEditor editor) {
        if ((savedState == null) || savedState.isEmpty()) {
            return;
        }
        MathModel model = editor.getModel().getMathModel();
        if (model instanceof Wtg) {
            editor.getWorkspaceEntry().saveMemento();
            Wtg wtg = (Wtg) model;
            for (State state : wtg.getStates()) {
                String ref = wtg.getNodeReference(state);
                Node underlyingNode = getUnderlyingModel().getNodeByReference(ref);
                if ((underlyingNode instanceof StgPlace) && savedState.containsKey(underlyingNode)
                        && (savedState.get(underlyingNode) > 0)) {
                    state.setInitial(true);
                    return;
                }
            }
        }
    }

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

    @Override
    public Decorator getDecorator(final GraphEditor editor) {
        return node -> {
            if (converter == null) {
                return null;
            }
            if (node instanceof VisualState) {
                return getStateDecoration((VisualState) node);
            }
            if (node instanceof VisualWaveform) {
                return getWaveformDecoration(editor.getModel(), (VisualWaveform) node);
            }
            if (node instanceof VisualEvent) {
                return getEventDecoration((VisualEvent) node);
            }
            if (node instanceof VisualLevelConnection) {
                return getLevelDecoration(editor.getModel(), (VisualLevelConnection) node);
            }
            return null;
        };
    }

    private Decoration getStateDecoration(VisualState state) {
        StgPlace p = converter.getRelatedPlace(state.getReferencedComponent());
        if (p == null) {
            return null;
        }
        return p.getTokens() > 0 ? StateDecoration.Marked.INSTANCE : StateDecoration.Unmarked.INSTANCE;
    }

    private Decoration getWaveformDecoration(VisualModel model, VisualWaveform waveform) {
        boolean isWaveformActive = !isInNodalState() && isContainerExcited(model, waveform);
        return isWaveformActive ? WaveformDecoration.Active.INSTANCE : WaveformDecoration.Inactive.INSTANCE;
    }

    private boolean isInNodalState() {
        Wtg wtg = converter.getSrcModel();
        for (State state : wtg.getStates()) {
            StgPlace place = converter.getRelatedPlace(state);
            if ((place != null) && (place.getTokens() > 0)) {
                return true;
            }
        }
        return false;
    }

    private Decoration getEventDecoration(VisualEvent event) {
        MathNode transition = getCurrentUnderlyingNode();
        final boolean isExcited = getExcitedTransitionOfEvent(event) != null;
        final boolean isSuggested = isExcited && converter.isRelated(event.getReferencedComponent(), transition);
        return new Decoration() {
            @Override
            public Color getColorisation() {
                return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
            }

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

    private Decoration getLevelDecoration(VisualModel model, VisualLevelConnection level) {
        MathNode transition = getCurrentUnderlyingNode();
        VisualEvent firstEvent = (VisualEvent) level.getFirst();
        VisualEvent secondEvent = (VisualEvent) level.getSecond();
        VisualSignal signal = secondEvent.getVisualSignal();

        Signal.State state = DtdUtils.getNextState(firstEvent.getReferencedComponent());
        NamedTransition enabledUnstableTransition = converter.getEnabledUnstableTransition(signal.getReferencedComponent());
        boolean isEnabledUnstable = (state == Signal.State.UNSTABLE) && (enabledUnstableTransition != null);
        boolean isExcitedWaveform = isContainerExcited(model, getWaveform(signal));

        final boolean isExcited = isEnabledUnstable && isExcitedWaveform;
        final boolean isSuggested = isExcited && (enabledUnstableTransition == transition);
        return new Decoration() {
            @Override
            public Color getColorisation() {
                return isExcited ? SimulationDecorationSettings.getExcitedComponentColor() : null;
            }

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

    private VisualWaveform getWaveform(VisualSignal signal) {
        if (signal != null) {
            Node parent = signal.getParent();
            if (parent instanceof VisualWaveform) {
                return (VisualWaveform) parent;
            }
        }
        return null;
    }

    private Transition getExcitedTransitionOfEvent(VisualEvent event) {
        if (event != null) {
            NamedTransition transition = converter.getRelatedTransition(event.getReferencedComponent());
            if ((transition != null) && isEnabledUnderlyingNode(transition)) {
                return transition;
            }
        }
        return null;
    }

    private Transition getExcitedTransitionOfSignal(VisualModel model, VisualSignal signal) {
        Transition result = null;
        VisualWaveform waveform = getWaveform(signal);
        if ((waveform != null) && isContainerExcited(model, waveform)) {
            result = converter.getEnabledUnstableTransition(signal.getReferencedComponent());
            if (result == null) {
                result = getExcitedTransitionOfEvent(signal.getVisualSignalEntry());
            }
            if (result == null) {
                for (VisualTransitionEvent transition : signal.getVisualTransitions()) {
                    result = getExcitedTransitionOfEvent(transition);
                    if (result != null) break;
                }
            }
            if (result == null) {
                result = getExcitedTransitionOfEvent(signal.getVisualSignalExit());
            }
        }
        return result;
    }

}