workcraft/workcraft

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

Summary

Maintainability
A
1 hr
Test Coverage
package org.workcraft.plugins.wtg;

import org.workcraft.dom.Connection;
import org.workcraft.dom.Container;
import org.workcraft.dom.Node;
import org.workcraft.dom.math.MathNode;
import org.workcraft.dom.references.Identifier;
import org.workcraft.dom.references.NameManager;
import org.workcraft.exceptions.InvalidConnectionException;
import org.workcraft.plugins.dtd.*;
import org.workcraft.plugins.wtg.observers.GuardNameSupervisor;
import org.workcraft.plugins.wtg.observers.InitialStateSupervisor;
import org.workcraft.plugins.wtg.observers.SignalTypeConsistencySupervisor;
import org.workcraft.plugins.wtg.utils.WtgUtils;
import org.workcraft.serialisation.References;
import org.workcraft.utils.Hierarchy;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class Wtg extends Dtd {

    public Wtg() {
        this(null, null);
    }

    public Wtg(Container root, References refs) {
        super(root, refs);
        new InitialStateSupervisor().attach(getRoot());
        new SignalTypeConsistencySupervisor(this).attach(getRoot());
        new GuardNameSupervisor(this).attach(getRoot());
    }

    @Override
    public void validateConnection(MathNode first, MathNode second) throws InvalidConnectionException {
        super.validateConnection(first, second);

        if (first == second) {
            throw new InvalidConnectionException("Self-loops are not allowed.");
        }

        if ((first instanceof Waveform) && (second instanceof Waveform)) {
            throw new InvalidConnectionException("Cannot directly connect waveforms.");
        }

        if ((first instanceof State) && (second instanceof State)) {
            throw new InvalidConnectionException("Cannot directly connect states.");
        }

        if ((first instanceof State) && (second instanceof Waveform)) {
            for (Connection connection : getConnections(second)) {
                if ((connection.getFirst() != first) && (connection.getSecond() == second)) {
                    throw new InvalidConnectionException("Waveform cannot have more than one preceding state.");
                }
            }
        }

        if ((first instanceof Waveform) && (second instanceof State)) {
            for (Connection connection : getConnections(second)) {
                if ((connection.getFirst() == first) && (connection.getSecond() != second)) {
                    throw new InvalidConnectionException("Waveform cannot have more than one succeeding state.");
                }
            }
        }
        if ((first instanceof TransitionEvent) && (second instanceof TransitionEvent)) {
            Signal firstSignal = ((TransitionEvent) first).getSignal();
            Signal secondSignal = ((TransitionEvent) second).getSignal();
            Node firstWaveform = firstSignal.getParent();
            Node secondWaveform = secondSignal.getParent();
            if (firstWaveform != secondWaveform) {
                throw new InvalidConnectionException("Cannot connect events from different waveforms.");
            }
        }
    }

    public final Collection<State> getStates() {
        return Hierarchy.getDescendantsOfType(getRoot(), State.class);
    }

    public final Collection<Waveform> getWaveforms() {
        return Hierarchy.getDescendantsOfType(getRoot(), Waveform.class);
    }

    public final Collection<Signal> getSignals(Container container) {
        if (container == null) {
            container = getRoot();
        }
        return Hierarchy.getDescendantsOfType(container, Signal.class);
    }

    public final Collection<Event> getEvents(Container container) {
        if (container == null) {
            container = getRoot();
        }
        return Hierarchy.getDescendantsOfType(container, Event.class);
    }

    public final Collection<TransitionEvent> getTransitions(Container container) {
        if (container == null) {
            container = getRoot();
        }
        return Hierarchy.getDescendantsOfType(container, TransitionEvent.class);
    }

    public final Collection<EntryEvent> getEntries(Container container) {
        if (container == null) {
            container = getRoot();
        }
        return Hierarchy.getDescendantsOfType(container, EntryEvent.class);
    }

    public final Collection<ExitEvent> getExits(Container container) {
        if (container == null) {
            container = getRoot();
        }
        return Hierarchy.getDescendantsOfType(container, ExitEvent.class);
    }

    public Collection<String> getSignalNames() {
        Set<String> result = new HashSet<>();
        for (Signal signal : getSignals()) {
            result.add(getName(signal));
        }
        return result;
    }

    public Collection<String> getSignalNames(Signal.Type type) {
        Set<String> result = new HashSet<>();
        for (Signal signal : getSignals(type)) {
            result.add(getName(signal));
        }
        return result;
    }

    public Signal.Type getSignalType(String signalName) {
        if (getSignalNames(Signal.Type.INPUT).contains(signalName)) {
            return Signal.Type.INPUT;
        } else if (getSignalNames(Signal.Type.OUTPUT).contains(signalName)) {
            return Signal.Type.OUTPUT;
        } else if (getSignalNames(Signal.Type.INTERNAL).contains(signalName)) {
            return Signal.Type.INTERNAL;
        }
        return null;
    }

    public final State getInitialState() {
        for (State state: getStates()) {
            if (state.isInitial()) {
                return state;
            }
        }
        return null;
    }

    @Override
    public void anonymise() {
        setTitle("");
        HashSet<String> takenNames = new HashSet<>(getSignalNames());
        for (MathNode node : Hierarchy.getDescendantsOfType(getRoot(), MathNode.class)) {
            String name = getName(node);
            if ((name != null) && !Identifier.isInternal(name) && !(node instanceof Signal)) {
                getReferenceManager().setDefaultName(node);
                takenNames.add(getName(node));
            }
        }
        NameManager nameManager = getReferenceManager().getNameManager(null);
        String prefix = nameManager.getPrefix(new Signal());
        int count = 0;
        for (String oldName : getSignalNames()) {
            String newName;
            do {
                newName = prefix + count++;
            } while (takenNames.contains(newName));
            WtgUtils.renameSignal(this, oldName, newName);
            takenNames.add(newName);
        }
    }

}