/** */ package statemachine.impl; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; import org.eclipse.emf.ecore.util.EObjectContainmentEList; import org.eclipse.emf.ecore.util.InternalEList; import statemachine.State; import statemachine.StateMachine; import statemachine.StatemachineFactory; import statemachine.StatemachinePackage; import statemachine.Transition; import statemachine.util.TransformationsToolBox; /** * <!-- begin-user-doc --> * An implementation of the model object '<em><b>State Machine</b></em>'. * <!-- end-user-doc --> * <p> * The following features are implemented: * <ul> * <li>{@link statemachine.impl.StateMachineImpl#getStates <em>States</em>}</li> * <li>{@link statemachine.impl.StateMachineImpl#getDelta <em>Delta</em>}</li> * </ul> * </p> * * @generated */ public class StateMachineImpl extends MinimalEObjectImpl.Container implements StateMachine { // Allows acces to transitions of this automaton // starting from a given state and labelled by // a given object. The keys of this map are instances // of class Key and // values are sets of transitions. private Map<Key, Set<Transition>> transitions = new HashMap<>(); // Allows acces to transitions of this automaton // arriving to a given state and labelled by // a given object. The keys of this map are instances // of class Key and // values are sets of transitions. private Map<Key, Set<Transition>> reverse = new HashMap<>(); /** * The cached value of the '{@link #getStates() <em>States</em>}' containment reference list. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @see #getStates() * @generated * @ordered */ protected EList<State> states; /** * The cached value of the '{@link #getDelta() <em>Delta</em>}' containment reference list. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @see #getDelta() * @generated * @ordered */ protected EList<Transition> delta; /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ protected StateMachineImpl() { super(); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override protected EClass eStaticClass() { return StatemachinePackage.Literals.STATE_MACHINE; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public EList<State> getStates() { if (states == null) { states = new EObjectContainmentEList<State>(State.class, this, StatemachinePackage.STATE_MACHINE__STATES); } return states; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public EList<Transition> getDelta() { if (delta == null) { delta = new EObjectContainmentEList<Transition>(Transition.class, this, StatemachinePackage.STATE_MACHINE__DELTA); } return delta; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public State addState(boolean initial, boolean terminal) { State s = StatemachineFactory.eINSTANCE.createState(); s.setInitial(initial); s.setTerminal(terminal); return s; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> terminals() { Set<State> term = new HashSet<>(); for(State s: states) if(s.isTerminal()) term.add(s); return term; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> accessibleStates() { return access(initials(), transitions); } protected Set<State> access(Set<State> start, Map<Key, Set<Transition>> map) { Set<State> current = start; Set<State> old; do { old = current; current = new HashSet<State>(); Iterator<State> i = old.iterator(); while (i.hasNext()) { State e = (State) i.next(); current.add(e); Iterator<String> j = alphabet().iterator(); while (j.hasNext()) { Iterator<Transition> k = find(map, e, j.next()).iterator(); while (k.hasNext()) { current.add(((Transition) k.next()).getEnd()); } } } } while (current.size() != old.size()); return current; } // Computes and return the set of all transitions, starting // from a given state and labelled by a given label // contained in a given Map protected Set<Transition> find(Map<Key, Set<Transition>> m, State e, Object l) { Key n = new Key(e, l); if (!m.containsKey(n)) return new HashSet<>(); return m.get(n); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> accessibleStates(Set<State> states) { return access(states, transitions); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> coAccessibleStates(Set<State> states) { return access(states, reverse); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> coAccessibleStates() { return access(terminals(), reverse); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> accessibleAndCoAccessibleStates() { Set<State> ac = accessibleStates(); ac.retainAll(coAccessibleStates()); return ac; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> deltaFrom(State from, State to) { Set<Transition> t = delta(from); for (Iterator<Transition> i = t.iterator(); i.hasNext();) { Transition tr = (Transition) i.next(); if (!to.equals(tr.getEnd())) i.remove(); } return t; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> deltaMinusOne(State state, Object label) { return find(reverse, state, label); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public void addTransition(Transition transition) { add(transitions, transition); Transition trans = StatemachineFactory.eINSTANCE.createTransition(); trans.setLabel(transition.getLabel()); trans.setEnd(transition.getEnd()); trans.setStart(transition.getStart()); add(reverse, trans); } // add a given transition in a given Map protected void add(Map<Key, Set<Transition>> m, Transition t) { Key n = new Key(t.getStart(), t.getLabel()); Set<Transition> s; if (!m.containsKey(n)) { s = new HashSet<Transition>(); m.put(n, s); } else s = m.get(n); s.add(t); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> accessibleStates(State st) { Set<State> s = new HashSet<>(); s.add(st); return access(s, transitions); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public boolean accept(EList<String> word) { Set<State> s = TransformationsToolBox.epsilonClosure(steps(word),this); s.retainAll(terminals()); return !s.isEmpty(); } public Set<State> steps(List<String> word) { Set<State> s = TransformationsToolBox.epsilonClosure(initials(), this); return steps(s, new BasicEList<>(word)); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<String> alphabet() { Set<String> alpha = new HashSet<>(); for(Transition t : delta) if(t.getLabel() instanceof String) alpha.add((String)t.getLabel()); return alpha; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> delta(State state, Object label) { return find(transitions, state, label); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> delta(State state) { Set<Transition> s = new HashSet<>(); Iterator<String> alphit = alphabet().iterator(); while (alphit.hasNext()) { s.addAll(delta(state, alphit.next())); } return s; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> delta(Set<State> s) { Set<Transition> ds = new HashSet<>(); Iterator<State> i = s.iterator(); while (i.hasNext()) { ds.addAll(delta((State) i.next())); } return ds; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> steps(Set<State> s, EList<String> word) { Iterator<String> it = word.iterator(); while (it.hasNext()) { Object o = it.next(); s = step(s, o); if (s.isEmpty()) return s; } return s; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> steps(State st, EList<String> word) { Set<State> s = new HashSet<>(); s.add(st); Iterator<String> it = word.iterator(); while (it.hasNext()) { Object o = it.next(); s = step(s, o); if (s.isEmpty()) return s; } return s; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> step(Set<State> s, Object o) { Set<State> ns = new HashSet<>(); Set<State> ec = TransformationsToolBox.epsilonClosure(s, this); Iterator<State> it = ec.iterator(); while (it.hasNext()) { State st = (State) it.next(); Iterator<Transition> it2 = delta(st).iterator(); while (it2.hasNext()) { Transition tr = (Transition) it2.next(); if (tr.getLabel() != null && tr.getLabel().equals(o)) ns.add(tr.getEnd()); } } return ns; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<State> initials() { Set<State> term = new HashSet<>(); for(State s: states) if(s.isInitial()) term.add(s); return term; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> */ public Set<Transition> deltaMinusOne(State st) { Set<Transition> s = new HashSet<Transition>(); Iterator<String> alphit = alphabet().iterator(); while (alphit.hasNext()) { s.addAll(deltaMinusOne(st, alphit.next())); } return s; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { switch (featureID) { case StatemachinePackage.STATE_MACHINE__STATES: return ((InternalEList<?>)getStates()).basicRemove(otherEnd, msgs); case StatemachinePackage.STATE_MACHINE__DELTA: return ((InternalEList<?>)getDelta()).basicRemove(otherEnd, msgs); } return super.eInverseRemove(otherEnd, featureID, msgs); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public Object eGet(int featureID, boolean resolve, boolean coreType) { switch (featureID) { case StatemachinePackage.STATE_MACHINE__STATES: return getStates(); case StatemachinePackage.STATE_MACHINE__DELTA: return getDelta(); } return super.eGet(featureID, resolve, coreType); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @SuppressWarnings("unchecked") @Override public void eSet(int featureID, Object newValue) { switch (featureID) { case StatemachinePackage.STATE_MACHINE__STATES: getStates().clear(); getStates().addAll((Collection<? extends State>)newValue); return; case StatemachinePackage.STATE_MACHINE__DELTA: getDelta().clear(); getDelta().addAll((Collection<? extends Transition>)newValue); return; } super.eSet(featureID, newValue); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public void eUnset(int featureID) { switch (featureID) { case StatemachinePackage.STATE_MACHINE__STATES: getStates().clear(); return; case StatemachinePackage.STATE_MACHINE__DELTA: getDelta().clear(); return; } super.eUnset(featureID); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public boolean eIsSet(int featureID) { switch (featureID) { case StatemachinePackage.STATE_MACHINE__STATES: return states != null && !states.isEmpty(); case StatemachinePackage.STATE_MACHINE__DELTA: return delta != null && !delta.isEmpty(); } return super.eIsSet(featureID); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override @SuppressWarnings("unchecked") public Object eInvoke(int operationID, EList<?> arguments) throws InvocationTargetException { switch (operationID) { case StatemachinePackage.STATE_MACHINE___ADD_STATE__BOOLEAN_BOOLEAN: return addState((Boolean)arguments.get(0), (Boolean)arguments.get(1)); case StatemachinePackage.STATE_MACHINE___TERMINALS: return terminals(); case StatemachinePackage.STATE_MACHINE___ACCESSIBLE_STATES: return accessibleStates(); case StatemachinePackage.STATE_MACHINE___ACCESSIBLE_STATES__SET: return accessibleStates((Set<State>)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___CO_ACCESSIBLE_STATES__SET: return coAccessibleStates((Set<State>)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___CO_ACCESSIBLE_STATES: return coAccessibleStates(); case StatemachinePackage.STATE_MACHINE___ACCESSIBLE_AND_CO_ACCESSIBLE_STATES: return accessibleAndCoAccessibleStates(); case StatemachinePackage.STATE_MACHINE___DELTA_FROM__STATE_STATE: return deltaFrom((State)arguments.get(0), (State)arguments.get(1)); case StatemachinePackage.STATE_MACHINE___DELTA_MINUS_ONE__STATE_OBJECT: return deltaMinusOne((State)arguments.get(0), arguments.get(1)); case StatemachinePackage.STATE_MACHINE___ADD_TRANSITION__TRANSITION: addTransition((Transition)arguments.get(0)); return null; case StatemachinePackage.STATE_MACHINE___ACCESSIBLE_STATES__STATE: return accessibleStates((State)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___ACCEPT__ELIST: return accept((EList<String>)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___ALPHABET: return alphabet(); case StatemachinePackage.STATE_MACHINE___DELTA__STATE_OBJECT: return delta((State)arguments.get(0), arguments.get(1)); case StatemachinePackage.STATE_MACHINE___DELTA__STATE: return delta((State)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___DELTA__SET: return delta((Set<State>)arguments.get(0)); case StatemachinePackage.STATE_MACHINE___STEPS__SET_ELIST: return steps((Set<State>)arguments.get(0), (EList<String>)arguments.get(1)); case StatemachinePackage.STATE_MACHINE___STEPS__STATE_ELIST: return steps((State)arguments.get(0), (EList<String>)arguments.get(1)); case StatemachinePackage.STATE_MACHINE___STEP__SET_OBJECT: return step((Set<State>)arguments.get(0), arguments.get(1)); case StatemachinePackage.STATE_MACHINE___INITIALS: return initials(); case StatemachinePackage.STATE_MACHINE___DELTA_MINUS_ONE__STATE: return deltaMinusOne((State)arguments.get(0)); } return super.eInvoke(operationID, arguments); } private class Key { private State s; private Object l; protected Key(State s, Object l) { this.s = s; this.l = l; } public boolean equals(Object o) { if (o == null) return false; try { Key t = (Key) o; boolean ret = (l == null ? t.l == null : l.equals(t.l)) && (s == null ? t.s == null : s.equals(t.s)); return ret; } catch (ClassCastException x) { return false; } } public int hashCode() { int x, y; if (s == null) x = 0; else x = s.hashCode(); if (l == null) y = 0; else y = l.hashCode(); return y << 16 | x; // return new java.awt.Point(x, y).hashCode(); } } } //StateMachineImpl