| /******************************************************************************* |
| * Copyright (c) 2010 protos software gmbh (http://www.protos.de). |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * CONTRIBUTORS: |
| * Thomas Schuetz and Henrik Rentz-Reichert (initial contribution) |
| * |
| *******************************************************************************/ |
| package org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map.Entry; |
| import org.eclipse.emf.common.notify.Notification; |
| 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.common.util.TreeIterator; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; |
| import org.eclipse.emf.ecore.util.EcoreUtil.Copier; |
| import org.eclipse.emf.ecore.util.InternalEList; |
| import org.eclipse.etrice.core.fsm.fSM.AbstractInterfaceItem; |
| import org.eclipse.etrice.core.fsm.fSM.ChoicePoint; |
| import org.eclipse.etrice.core.fsm.fSM.ComponentCommunicationType; |
| import org.eclipse.etrice.core.fsm.fSM.ContinuationTransition; |
| import org.eclipse.etrice.core.fsm.fSM.DetailCode; |
| import org.eclipse.etrice.core.fsm.fSM.EntryPoint; |
| import org.eclipse.etrice.core.fsm.fSM.ExitPoint; |
| import org.eclipse.etrice.core.fsm.fSM.FSMFactory; |
| import org.eclipse.etrice.core.fsm.fSM.FSMPackage; |
| import org.eclipse.etrice.core.fsm.fSM.GuardedTransition; |
| import org.eclipse.etrice.core.fsm.fSM.InitialTransition; |
| import org.eclipse.etrice.core.fsm.fSM.MessageFromIf; |
| import org.eclipse.etrice.core.fsm.fSM.ModelComponent; |
| import org.eclipse.etrice.core.fsm.fSM.NonInitialTransition; |
| import org.eclipse.etrice.core.fsm.fSM.RefinedState; |
| import org.eclipse.etrice.core.fsm.fSM.RefinedTransition; |
| import org.eclipse.etrice.core.fsm.fSM.State; |
| import org.eclipse.etrice.core.fsm.fSM.StateGraph; |
| import org.eclipse.etrice.core.fsm.fSM.StateGraphItem; |
| import org.eclipse.etrice.core.fsm.fSM.StateGraphNode; |
| import org.eclipse.etrice.core.fsm.fSM.StateTerminal; |
| import org.eclipse.etrice.core.fsm.fSM.TrPoint; |
| import org.eclipse.etrice.core.fsm.fSM.TrPointTerminal; |
| import org.eclipse.etrice.core.fsm.fSM.Transition; |
| import org.eclipse.etrice.core.fsm.fSM.TransitionPoint; |
| import org.eclipse.etrice.core.fsm.fSM.Trigger; |
| import org.eclipse.etrice.core.fsm.fSM.TriggeredTransition; |
| import org.eclipse.etrice.core.fsm.naming.FSMNameProvider; |
| import org.eclipse.etrice.core.fsm.util.FSMHelpers; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.ActiveTrigger; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.ExpandedModelComponent; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.ExpandedRefinedState; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.FsmGenFactory; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.FsmGenPackage; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.IDiagnostician; |
| import org.eclipse.etrice.core.genmodel.fsm.fsmgen.TransitionChain; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * An implementation of the model object '<em><b>Expanded Actor Class</b></em>'. |
| * <!-- end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * <ul> |
| * <li>{@link org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl.ExpandedModelComponentImpl#getModelComponent <em>Model Component</em>}</li> |
| * <li>{@link org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl.ExpandedModelComponentImpl#getStateMachine <em>State Machine</em>}</li> |
| * <li>{@link org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl.ExpandedModelComponentImpl#getTransitionChains <em>Transition Chains</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @generated |
| */ |
| public class ExpandedModelComponentImpl extends MinimalEObjectImpl.Container implements ExpandedModelComponent { |
| |
| /** |
| * The cached value of the '{@link #getModelComponent() <em>Model Component</em>}' reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getModelComponent() |
| * @generated |
| * @ordered |
| */ |
| protected ModelComponent modelComponent; |
| |
| private static class NodeData { |
| private LinkedList<Transition> inTrans = new LinkedList<Transition>(); |
| private LinkedList<Transition> outTrans = new LinkedList<Transition>(); |
| private LinkedList<Transition> loopTrans = null; |
| |
| LinkedList<Transition> getInTrans() { |
| return inTrans; |
| } |
| |
| LinkedList<Transition> getOutTrans() { |
| return outTrans; |
| } |
| |
| LinkedList<Transition> getLoopTransitions() { |
| if (loopTrans==null) { |
| loopTrans = new LinkedList<Transition>(); |
| for (Transition t : getOutTrans()) { |
| // outgoing transitions always are NonInitialTransitions |
| NonInitialTransition tr = (NonInitialTransition) t; |
| |
| if (tr.getFrom() instanceof StateTerminal) { |
| if (tr.getTo() instanceof StateTerminal) { |
| if (((StateTerminal)tr.getFrom()).getState() == ((StateTerminal)tr.getTo()).getState()) |
| loopTrans.add(tr); |
| } |
| } |
| else if (tr.getFrom() instanceof TrPointTerminal) { |
| if (tr.getTo() instanceof TrPointTerminal) { |
| if (((TrPointTerminal)tr.getFrom()).getTrPoint() == ((TrPointTerminal)tr.getTo()).getTrPoint()) |
| loopTrans.add(tr); |
| } |
| } |
| } |
| } |
| return loopTrans; |
| } |
| } |
| |
| /** |
| * transition chains may merge in a choice point or in an entry or exit point. |
| * We call all merged transition chains a transition chain bundle |
| * |
| */ |
| protected static class TransitionChainBundle { |
| private BasicEList<TransitionChain> chains = new BasicEList<TransitionChain>(); |
| private EObject commonData = null; |
| } |
| |
| protected class TransitionToChainBundleMap extends HashMap<Transition, TransitionChainBundle> { |
| private static final long serialVersionUID = 1L; |
| |
| void put(Transition t, TransitionChain tc) { |
| TransitionChainBundle tcb = get(t); |
| if (tcb==null) { |
| tcb = new TransitionChainBundle(); |
| put(t, tcb); |
| } |
| tcb.chains.add(tc); |
| } |
| |
| /* (non-Javadoc) |
| * @see java.util.AbstractMap#toString() |
| */ |
| // @Override |
| // public String toString() { |
| // StringBuffer result = new StringBuffer(); |
| // for (java.util.Map.Entry<Transition, TransitionChainBundle> entry : entrySet()) { |
| // result.append("transition "+fsmNameProvider.getFullPath(entry.getKey())+":\n"); |
| // TransitionChainBundle bundle = entry.getValue(); |
| // for (TransitionChain tc : bundle.chains) { |
| // String data = tc.getData()!=null? " with data "+tc.getData().getRefType().getType().getName() : ""; |
| // result.append(" chain starting at "+fsmNameProvider.getFullPath(tc.getTransition())+data+"\n"); |
| // } |
| // String data = bundle.commonData!=null? bundle.commonData.getRefType().getType().getName() : "-"; |
| // result.append(" bundle data "+data+"\n"); |
| // } |
| // return result.toString(); |
| // } |
| } |
| |
| /** |
| * The cached value of the '{@link #getStateMachine() <em>State Machine</em>}' containment reference. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getStateMachine() |
| * @generated |
| * @ordered |
| */ |
| protected StateGraph stateMachine; |
| |
| /** |
| * The cached value of the '{@link #getTransitionChains() <em>Transition Chains</em>}' containment reference list. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getTransitionChains() |
| * @generated |
| * @ordered |
| */ |
| protected EList<TransitionChain> transitionChains; |
| |
| private static final String TRIGGER_SEP = "#"; |
| |
| private IDiagnostician validator; |
| |
| private boolean prepared = false; |
| private HashSet<StateGraphItem> ownObjects = null; |
| private HashSet<Transition> targetsOfRefinedTransitions = null; |
| private HashSet<Transition> baseTransitionHasDetailCode = null; |
| private HashMap<AbstractInterfaceItem, Integer> ifitem2localId = null; |
| private HashMap<StateGraphNode, NodeData> node2data = null; |
| private HashMap<State, LinkedList<ActiveTrigger>> state2triggers = null; |
| private HashMap<String, MessageFromIf> triggerstring2mif = null; |
| private LinkedList<TransitionChain> trchains = null; |
| private TransitionToChainBundleMap trans2chainBundle = null; |
| private HashMap<EObject, EObject> copy2orig = null; |
| |
| private FSMHelpers fsmHelpers = new FSMHelpers(); |
| protected FSMNameProvider fsmNameProvider = new FSMNameProvider(); |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| protected ExpandedModelComponentImpl() { |
| super(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() { |
| return FsmGenPackage.Literals.EXPANDED_MODEL_COMPONENT; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public ModelComponent getModelComponent() { |
| if (modelComponent != null && modelComponent.eIsProxy()) { |
| InternalEObject oldModelComponent = (InternalEObject)modelComponent; |
| modelComponent = (ModelComponent)eResolveProxy(oldModelComponent); |
| if (modelComponent != oldModelComponent) { |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.RESOLVE, FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT, oldModelComponent, modelComponent)); |
| } |
| } |
| return modelComponent; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public ModelComponent basicGetModelComponent() { |
| return modelComponent; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setModelComponent(ModelComponent newModelComponent) { |
| ModelComponent oldModelComponent = modelComponent; |
| modelComponent = newModelComponent; |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT, oldModelComponent, modelComponent)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public StateGraph getStateMachine() { |
| return stateMachine; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public NotificationChain basicSetStateMachine(StateGraph newStateMachine, NotificationChain msgs) { |
| StateGraph oldStateMachine = stateMachine; |
| stateMachine = newStateMachine; |
| if (eNotificationRequired()) { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE, oldStateMachine, newStateMachine); |
| if (msgs == null) msgs = notification; else msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setStateMachine(StateGraph newStateMachine) { |
| if (newStateMachine != stateMachine) { |
| NotificationChain msgs = null; |
| if (stateMachine != null) |
| msgs = ((InternalEObject)stateMachine).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE, null, msgs); |
| if (newStateMachine != null) |
| msgs = ((InternalEObject)newStateMachine).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE, null, msgs); |
| msgs = basicSetStateMachine(newStateMachine, msgs); |
| if (msgs != null) msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE, newStateMachine, newStateMachine)); |
| } |
| |
| protected void validationError(String msg, EObject obj, EStructuralFeature feature) { |
| validationError(msg, obj, feature, IDiagnostician.INSIGNIFICANT_INDEX); |
| } |
| |
| protected void validationError(String msg, EObject obj, EStructuralFeature feature, int idx) { |
| // assert obj.eResource() != null : "val error in artificial model object"; |
| if (obj.eResource()==null) { |
| obj = copy2orig.get(obj); |
| } |
| validator.error(msg, obj, feature, idx); |
| } |
| |
| private void buildStateGraph() { |
| // create a list of state machines, derived first, base last |
| ArrayList<StateGraph> stateMachines = new ArrayList<StateGraph>(); |
| ModelComponent orig = getModelComponent(); |
| if (orig.getStateMachine()!=null) |
| stateMachines.add(orig.getStateMachine()); |
| while (orig.getBase()!=null) { |
| orig = orig.getBase(); |
| if (orig.getStateMachine()!=null) |
| stateMachines.add(orig.getStateMachine()); |
| } |
| |
| Collection<StateGraph> copiedStateMachines = createCopyOfStateMachines(stateMachines); |
| |
| collectContentsInNewStateMachine(copiedStateMachines); |
| |
| introduceExpandedRefinedStates(getStateMachine()); |
| } |
| |
| private void collectContentsInNewStateMachine(Collection<StateGraph> copiedStateMachines) { |
| // move all state machine contents to our state machine (which we create newly) |
| StateGraph myStateMachine = FSMFactory.eINSTANCE.createStateGraph(); |
| setStateMachine(myStateMachine); |
| |
| HashMap<Transition, DetailCode> trans2refinedAction = new HashMap<Transition, DetailCode>(); |
| for (StateGraph copiedStateMachine : copiedStateMachines) { |
| myStateMachine.getChPoints().addAll(copiedStateMachine.getChPoints()); |
| myStateMachine.getStates().addAll(copiedStateMachine.getStates()); |
| myStateMachine.getTrPoints().addAll(copiedStateMachine.getTrPoints()); |
| myStateMachine.getTransitions().addAll(copiedStateMachine.getTransitions()); |
| |
| // collect the refined action code in a hash map |
| for (RefinedTransition rt : copiedStateMachine.getRefinedTransitions()) { |
| if (rt.getAction()==null || rt.getAction().getLines().isEmpty()) |
| continue; |
| |
| DetailCode code = trans2refinedAction.get(rt.getTarget()); |
| if (code==null) { |
| code = FSMFactory.eINSTANCE.createDetailCode(); |
| trans2refinedAction.put(rt.getTarget(), code); |
| } |
| |
| code.getLines().addAll(0, rt.getAction().getLines()); |
| code.setUsed(fsmHelpers.hasDetailCode(code)); |
| } |
| } |
| |
| // for refined transitions we just append the action code to the target |
| // we can do this since the target is a copy just for this class |
| for (Entry<Transition, DetailCode> entry : trans2refinedAction.entrySet()) { |
| ownObjects.add(entry.getKey()); |
| targetsOfRefinedTransitions.add(entry.getKey()); |
| if (entry.getKey().getAction()==null) { |
| entry.getKey().setAction(entry.getValue()); |
| } |
| else { |
| baseTransitionHasDetailCode.add(entry.getKey()); |
| entry.getKey().getAction().getLines().addAll(entry.getValue().getLines()); |
| } |
| } |
| } |
| |
| private Collection<StateGraph> createCopyOfStateMachines(List<StateGraph> origStateMachines) { |
| // create a self contained copy of all actor classes |
| // references to interface items (ports, saps and spps) point to contents of the original actor class |
| // Collection<StateGraph> all = EcoreUtil.copyAll(sms); |
| // we use the copier directly since we need access to the map |
| Copier copier = new Copier(); |
| Collection<StateGraph> copiedStateMachines = copier.copyAll(origStateMachines); |
| copier.copyReferences(); |
| for (EObject o : copier.keySet()) { |
| EObject c = copier.get(o); |
| copy2orig.put(c, o); |
| } |
| |
| if (getModelComponent().getStateMachine()!=null) { |
| // first state machine is ours |
| StateGraph self = copiedStateMachines.iterator().next(); |
| |
| // flag own objects |
| TreeIterator<EObject> it = self.eAllContents(); |
| while (it.hasNext()) { |
| EObject obj = it.next(); |
| if (obj instanceof StateGraphItem) |
| addOwnObject((StateGraphItem)obj); |
| } |
| } |
| return copiedStateMachines; |
| } |
| |
| /** |
| * replace refined state with a ExpandedRefinedState but as replacement of the ultimate SimpleState |
| * the refined state is targeting |
| * |
| * @param sg - the current context (will be called recursively) |
| */ |
| private void introduceExpandedRefinedStates(StateGraph sg) { |
| // need to make a copy of the list because we will modify the original list |
| ArrayList<State> states = new ArrayList<State>(sg.getStates()); |
| for (State s : states) { |
| if (s instanceof RefinedState) { |
| RefinedState rs = (RefinedState) s; |
| |
| ExpandedRefinedState state = FsmGenFactory.eINSTANCE.createExpandedRefinedState(); |
| state.init(rs); |
| copy2orig.put(state, getOrig(rs)); |
| if (isOwnObject(rs)) |
| addOwnObject(state); |
| } |
| } |
| |
| // recurse down into sub graph |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| introduceExpandedRefinedStates(s.getSubgraph()); |
| } |
| } |
| |
| private void addOutgoingTransition(StateGraphNode node, Transition t) { |
| NodeData data = node2data.get(node); |
| if (data==null) { |
| data = new NodeData(); |
| node2data.put(node, data); |
| } |
| data.getOutTrans().add(t); |
| } |
| |
| private void addIncomingTransition(StateGraphNode node, Transition t) { |
| NodeData data = node2data.get(node); |
| if (data==null) { |
| data = new NodeData(); |
| node2data.put(node, data); |
| } |
| data.getInTrans().add(t); |
| } |
| |
| private void findOutgoingTransitions(StateGraph sg) { |
| // depth first: recurse into sub graphs of states |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| findOutgoingTransitions(s.getSubgraph()); |
| } |
| |
| for (Transition t : sg.getTransitions()) { |
| addIncomingTransition(getAdjustedTargetNode(t), t); |
| if (t instanceof NonInitialTransition) { |
| addOutgoingTransition(fsmHelpers.getNode(((NonInitialTransition)t).getFrom()), t); |
| } |
| } |
| } |
| |
| /** |
| * @param sg |
| */ |
| private void checkTransitionChains(StateGraph sg) { |
| for (Transition t : sg.getTransitions()) { |
| TransitionChain chain = getChain(t); |
| if (chain==null) |
| if (!getModelComponent().isAbstract()) { |
| int idx = sg.getTransitions().indexOf(t); |
| Transition orig = (Transition) copy2orig.get(t); |
| String name = fsmNameProvider.getName(orig); |
| validator.error("transition '"+name+"' is not part of a transition chain (only allowed for abstract actor classes)", orig.eContainer(), FSMPackage.eINSTANCE.getStateGraph_Transitions(), idx); |
| } |
| } |
| |
| // recursion |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| checkTransitionChains(s.getSubgraph()); |
| } |
| } |
| |
| private void doChecks(StateGraph sg) { |
| |
| // check if empty |
| if (sg.getTransitions().isEmpty() && sg.getStates().isEmpty() |
| && sg.getChPoints().isEmpty() && sg.getTrPoints().isEmpty()) |
| return; |
| |
| int initCount = 0; |
| for (Transition t : sg.getTransitions()) { |
| if (t instanceof InitialTransition) |
| ++initCount; |
| } |
| if (initCount==0) { |
| if (sg.eContainer() instanceof State) { |
| if (!getModelComponent().isAbstract()) { |
| // having no initial transition in a nested state is valid only if there is no transition to history |
| // except of self transitions |
| // i.e. no incoming transition of the state itself |
| NodeData data = node2data.get((State)sg.eContainer()); |
| if (data!=null && data.getLoopTransitions().size()!=data.getInTrans().size()) |
| validationError(getModelComponentName()+": Having no initial transition in a nested state is valid only if there is no transition to history except of self transitions!", |
| sg.eContainer(), FSMPackage.eINSTANCE.getState_Subgraph()); |
| } |
| } |
| else { |
| validationError(getModelComponentName()+": The TOP level has to have an initial transition!", getModelComponent().getStateMachine(), FSMPackage.eINSTANCE.getStateGraph_Transitions()); |
| } |
| } |
| else { |
| if (initCount>1) |
| validationError(getModelComponentName()+": There has to be exactly one initial transition!", getModelComponent().getStateMachine(), FSMPackage.eINSTANCE.getStateGraph_Transitions()); |
| } |
| |
| for (ChoicePoint cp : sg.getChPoints()) { |
| NodeData data = node2data.get(cp); |
| |
| ChoicePoint orig = (ChoicePoint) copy2orig.get(cp); |
| StateGraph origContainer = (StateGraph) orig.eContainer(); |
| int idx = origContainer.getChPoints().indexOf(orig); |
| |
| if (data==null) { |
| validationError(getModelComponentName()+": ChoicePoint is not connected!", origContainer, FSMPackage.eINSTANCE.getStateGraph_ChPoints(), idx); |
| } |
| else { |
| // several incoming transitions possible, see bug 340496 |
| // if (data.getInTrans().size()!=1) |
| // validationError(getModelComponentName()+": ChoicePoint has "+data.getInTrans().size()+" incoming transitions!", sg, FSMPackage.eINSTANCE.getStateGraph_ChPoints(), idx); |
| if (data.getOutTrans().size()<2) |
| validationError(getModelComponentName()+": ChoicePoint should have 2 or more branches but has "+data.getOutTrans().size(), origContainer, FSMPackage.eINSTANCE.getStateGraph_ChPoints(), idx); |
| if (getDefaultBranch(data.getOutTrans())==null) |
| validationError(getModelComponentName()+": ChoicePoint has no default branch!", origContainer, FSMPackage.eINSTANCE.getStateGraph_ChPoints(), idx); |
| if (!data.getLoopTransitions().isEmpty()) |
| validationError(getModelComponentName()+": ChoicePoint is connected to itself!", origContainer, FSMPackage.eINSTANCE.getStateGraph_ChPoints(), idx); |
| } |
| } |
| |
| for (TrPoint tp : sg.getTrPoints()) { |
| NodeData data = node2data.get(tp); |
| |
| TrPoint orig = (TrPoint) copy2orig.get(tp); |
| StateGraph origContainer = (StateGraph) orig.eContainer(); |
| int idx = origContainer.getTrPoints().indexOf(orig); |
| |
| if (data==null) { |
| if (!getModelComponent(tp).isAbstract()) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" is not connected", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| } |
| else { |
| if ((tp instanceof EntryPoint)||(tp instanceof ExitPoint)) { |
| // non-abstract classes must have incoming transitions for entry and exit points |
| if (!getModelComponent().isAbstract() && data.getInTrans().isEmpty()) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" has no incoming transition!", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| |
| if (getModelComponent(tp).isAbstract()) { |
| // transition points inherited from abstract base classes |
| // (of from abstract classes themselves) must not have more than one outgoing transition |
| if (data.getOutTrans().size()>1) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" must have at most one outgoing transition!", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| } |
| else { |
| // non-abstract or non-inherited transition points must have one outgoing transition |
| if (data.getOutTrans().size()!=1) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" must have exactly one outgoing transition!", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| } |
| |
| if (!data.getLoopTransitions().isEmpty()) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" must have no self transitions!", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| } |
| else if (tp instanceof TransitionPoint) { |
| if (data.getOutTrans().size()<data.getLoopTransitions().size()) |
| validationError(getModelComponentName()+": TrPoint "+fsmNameProvider.getFullPath(tp)+" must have no incoming transitions!", origContainer, FSMPackage.eINSTANCE.getStateGraph_TrPoints(), idx); |
| } |
| } |
| } |
| |
| // recurse into sub graphs of states |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| doChecks(s.getSubgraph()); |
| } |
| } |
| |
| private void findTriggersOfState(State s) { |
| LinkedList<ActiveTrigger> triggers = new LinkedList<ActiveTrigger>(); |
| HashMap<String, ActiveTrigger> caughtTriggers = new HashMap<String, ActiveTrigger>(); |
| collectTriggersAndTransitions(s, caughtTriggers, triggers); |
| state2triggers.put(s, triggers); |
| } |
| |
| private String getTriggerString(MessageFromIf mifp) { |
| assert(mifp.getFrom().getName()!=null) : "ifitem name must not be null"; |
| assert(fsmNameProvider.getMessageName(mifp.getMessage())!=null) : "message name must not be null"; |
| return mifp.getFrom().getName()+TRIGGER_SEP+fsmNameProvider.getMessageName(mifp.getMessage()); |
| } |
| |
| private void collectOutgoingTransitions(EList<Transition> sameLevelTransitions, |
| HashMap<String, ActiveTrigger> caughtTriggers, |
| LinkedList<ActiveTrigger> triggers) { |
| for (Transition t : sameLevelTransitions) { |
| if (t instanceof TriggeredTransition) { |
| TriggeredTransition tt = (TriggeredTransition) t; |
| |
| for (Trigger trig : ((TriggeredTransition)t).getTriggers()) { |
| for (MessageFromIf mifp : trig.getMsgFromIfPairs()) { |
| String tr = getTriggerString(mifp); |
| ActiveTrigger at = caughtTriggers.get(tr); |
| /* |
| * accept new trigger if |
| * |
| * - no inner or inner with guard |
| * - accept several but only one without guard (count), |
| * insert those with guard first in the list of the _same_ level(!) |
| */ |
| if (at==null) { |
| // no inner transition with this trigger exists, |
| // so this is a new trigger (and our unique point of ActiveTrigger creation) |
| at = FsmGenFactory.eINSTANCE.createActiveTrigger(); |
| at.setMsg(mifp.getMessage()); |
| at.setIfitem(mifp.getFrom()); |
| at.setTrigger(tr); |
| at.getTransitions().add(tt); |
| caughtTriggers.put(tr, at); |
| triggers.add(at); |
| } |
| else { |
| // check guards of previous transitions |
| TriggeredTransition unguarded = null; |
| boolean accepted = true; |
| for (TriggeredTransition t2 : at.getTransitions()) { |
| for (Trigger trig2 : t2.getTriggers()) { |
| if (isMatching(trig2, tr)) { |
| if (!fsmHelpers.isGuarded(trig2)) { |
| unguarded = t2; |
| if (!sameLevelTransitions.contains(t2)) |
| accepted = false; |
| } |
| } |
| } |
| } |
| if (accepted) { |
| if (unguarded!=null) { |
| // there already is an unguarded transition: require a quard |
| if (!fsmHelpers.isGuarded(trig)) { |
| validationError("Transitions with same trigger on same level have to be guarded!", t, FSMPackage.eINSTANCE.getTriggeredTransition_Triggers()); |
| } |
| else { |
| int idx = at.getTransitions().indexOf(unguarded); |
| at.getTransitions().add(idx, tt); |
| } |
| } |
| else { |
| // just add at the end |
| at.getTransitions().add(tt); |
| } |
| } |
| // else: this trigger is already satisfied - nevertheless this is a valid situation |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private void collectTriggersAndTransitions(State s, |
| HashMap<String, ActiveTrigger> caughtTriggers, |
| LinkedList<ActiveTrigger> triggers) { |
| // consider outgoing transitions of this state |
| collectOutgoingTransitions(getOutgoingTransitions(s), caughtTriggers, triggers); |
| |
| // consider TransitionPoint transitions |
| if (s.eContainer() instanceof StateGraph) { |
| StateGraph sg = (StateGraph) s.eContainer(); |
| BasicEList<Transition> trpTransitions = new BasicEList<Transition>(); |
| for (TrPoint tp : sg.getTrPoints()) { |
| trpTransitions.addAll(getOutgoingTransitions(tp)); |
| } |
| collectOutgoingTransitions(trpTransitions, caughtTriggers, triggers); |
| |
| // go to surrounding context |
| if (sg.eContainer() instanceof State) { |
| collectTriggersAndTransitions((State) sg.eContainer(), caughtTriggers, triggers); |
| } |
| } |
| else { |
| // this should never happen |
| assert(false): "A State must always reside in a StateGraph!"; |
| } |
| } |
| |
| private void findLeafStateTriggers(StateGraph sg) { |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| findLeafStateTriggers(s.getSubgraph()); |
| else |
| findTriggersOfState(s); |
| } |
| } |
| |
| private void fillTriggerStringMap() { |
| // improve performance using maps name2ifitem and name2msgs |
| HashMap<String, AbstractInterfaceItem> name2ifitem = new HashMap<String, AbstractInterfaceItem>(); |
| HashMap<String, List<EObject>> name2msgs = new HashMap<String, List<EObject>>(); |
| List<AbstractInterfaceItem> items = getAllInterfaceItems(); |
| for (AbstractInterfaceItem item : items) { |
| name2ifitem.put(item.getName(), item); |
| name2msgs.put(item.getName(), getIncomingMessages(item)); |
| } |
| |
| // compute a set of all trigger strings |
| HashSet<String> triggers = new HashSet<String>(); |
| for (LinkedList<ActiveTrigger> ttlist : state2triggers.values()) { |
| for (ActiveTrigger tt : ttlist) { |
| triggers.add(tt.getTrigger()); |
| } |
| } |
| |
| // now fill triggerstring2mif |
| for (String trig : triggers) { |
| String[] parts = trig.split(TRIGGER_SEP); |
| |
| // this should always hold true |
| assert(parts.length==2): "By our convention triggers are composed of two parts separated by " |
| +TRIGGER_SEP+". Here we have '"+trig+"' which doesn't consist of two parts!"; |
| |
| AbstractInterfaceItem ii = name2ifitem.get(parts[0]); |
| |
| // this should always hold true |
| assert(ii!=null): "The name '"+parts[0]+"' did not match an interface item (in name2ifitem)!"; |
| |
| List<EObject> msgs = name2msgs.get(parts[0]); |
| |
| // this should always hold true |
| assert(msgs!=null): "The name '"+parts[0]+"' did not match an interface item (in name2msgs)!"; |
| |
| EObject msg = null; |
| for (EObject m : msgs) { |
| if (fsmNameProvider.getMessageName(m).equals(parts[1])) |
| msg = m; |
| } |
| |
| // this should always hold true |
| assert(msg!=null): "The message '"+parts[1]+"' did not match a message!"; |
| |
| MessageFromIf mif = FSMFactory.eINSTANCE.createMessageFromIf(); |
| mif.setFrom(ii); |
| mif.setMessage(msg); |
| triggerstring2mif.put(trig, mif); |
| } |
| } |
| |
| private void collectChainTransitions(TransitionChain tc, Transition t) { |
| trans2chainBundle.put(t, tc); |
| |
| StateGraphNode node = fsmHelpers.getNode(t.getTo()); |
| |
| // the chain ends if a state is reached |
| if (node instanceof State) |
| return; |
| |
| // the chain ends if source and destination coincide |
| if (tc.getTransition() instanceof NonInitialTransition && node==fsmHelpers.getNode(((NonInitialTransition)tc.getTransition()).getFrom())) |
| return; |
| |
| for (Transition next : getOutgoingTransitions(node)) { |
| // from the second transition in the chain on we have: |
| if (next instanceof TriggeredTransition) { |
| TriggeredTransition orig = (TriggeredTransition)copy2orig.get(next); |
| StateGraph origContainer = (StateGraph) orig.eContainer(); |
| int idx = origContainer.getTransitions().indexOf(orig); |
| validationError("Segments following the triggering transition can have no triggers!\n", origContainer, FSMPackage.eINSTANCE.getStateGraph_Transitions(), idx); |
| } |
| |
| collectChainTransitions(tc, next); |
| } |
| } |
| |
| private void findTransitionChains(StateGraph sg, Class<?> cls) { |
| findTransitionChains(sg, cls, true); |
| } |
| |
| private void findTransitionChains(StateGraph sg, Class<?> cls, boolean includeInitial) { |
| for (Transition t : sg.getTransitions()) { |
| if (cls.isInstance(t) || (includeInitial && (t instanceof InitialTransition))) { |
| addTransitionChain(t); |
| } |
| } |
| |
| // recurse into sub graphs of states |
| for (State s : sg.getStates()) { |
| if (s.getSubgraph()!=null) |
| findTransitionChains(s.getSubgraph(), cls, includeInitial); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void prepare(IDiagnostician validator) { |
| if (prepared) |
| return; |
| |
| prepared = true; |
| |
| this.validator = validator; |
| |
| ifitem2localId = new HashMap<AbstractInterfaceItem, Integer>(); |
| ownObjects = new HashSet<StateGraphItem>(); |
| targetsOfRefinedTransitions = new HashSet<Transition>(); |
| baseTransitionHasDetailCode = new HashSet<Transition>(); |
| node2data = new HashMap<StateGraphNode, NodeData>(); |
| state2triggers = new HashMap<State, LinkedList<ActiveTrigger>>(); |
| triggerstring2mif = new HashMap<String, MessageFromIf>(); |
| trchains = new LinkedList<TransitionChain>(); |
| trans2chainBundle = new TransitionToChainBundleMap(); |
| copy2orig = new HashMap<EObject, EObject>(); |
| |
| buildStateGraph(); |
| computeInterfaceItemLocalIds(getModelComponent(), 0); |
| findOutgoingTransitions(getStateMachine()); |
| |
| doChecks(getStateMachine()); |
| if (validator.isFailed()) |
| return; |
| |
| if (getModelComponent().getCommType()==ComponentCommunicationType.DATA_DRIVEN) { |
| findTransitionChains(getStateMachine(), GuardedTransition.class); |
| } |
| else if (getModelComponent().getCommType()==ComponentCommunicationType.ASYNCHRONOUS) { |
| findLeafStateTriggers(getStateMachine()); |
| fillTriggerStringMap(); |
| findTransitionChains(getStateMachine(), TriggeredTransition.class); |
| computeCommonChainData(); |
| findTransitionChains(getStateMachine(), GuardedTransition.class, false); |
| checkTransitionChains(getStateMachine()); |
| } |
| else { |
| // event driven state machine |
| findLeafStateTriggers(getStateMachine()); |
| fillTriggerStringMap(); |
| findTransitionChains(getStateMachine(), TriggeredTransition.class); |
| computeCommonChainData(); |
| checkTransitionChains(getStateMachine()); |
| } |
| } |
| |
| /** |
| * |
| */ |
| private void computeCommonChainData() { |
| for (TransitionChainBundle tcb : trans2chainBundle.values()) { |
| tcb.commonData = computeCommonChainData(tcb.chains); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void release() { |
| if (!prepared) |
| return; |
| |
| prepared = false; |
| |
| // release resources |
| ifitem2localId = null; |
| ownObjects = null; |
| node2data = null; |
| state2triggers = null; |
| triggerstring2mif = null; |
| trchains = null; |
| trans2chainBundle = null; |
| copy2orig = null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public void addOwnObject(StateGraphItem obj) { |
| ownObjects.add(obj); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isOwnObject(StateGraphItem obj) { |
| return ownObjects.contains(obj); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean hasBaseTransitionDetailCode(Transition trans) { |
| return baseTransitionHasDetailCode.contains(trans); |
| } |
| |
| private int computeInterfaceItemLocalIds(ModelComponent mc, int offset) { |
| if (mc.getBase()!=null) { |
| // first recurse into base class |
| offset = computeInterfaceItemLocalIds(mc.getBase(), offset); |
| } |
| |
| EList<AbstractInterfaceItem> items = getOwnInterfaceItems(mc); |
| for (AbstractInterfaceItem item : items) { |
| ifitem2localId.put(item, offset); |
| ++offset; |
| } |
| |
| return offset; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public int getInterfaceItemLocalId(AbstractInterfaceItem ifitem) { |
| Integer localId = ifitem2localId.get(ifitem); |
| if (localId!=null) |
| return localId.intValue(); |
| else |
| return -1; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @return |
| * @generated NOT |
| */ |
| public EObject computeCommonChainData(EList<TransitionChain> chains) { |
| return null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean hasStateMachine() { |
| ModelComponent mc = getModelComponent(); |
| while (mc!=null) { |
| if (mc.getStateMachine()!=null) |
| return true; |
| mc = mc.getBase(); |
| } |
| return false; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public String getTriggerCodeName(MessageFromIf mif) { |
| return "TRIG_"+mif.getFrom().getName()+"__"+fsmNameProvider.getMessageName(mif.getMessage()); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public String getTriggerCodeName(ActiveTrigger at) { |
| String[] parts = at.getTrigger().split(TRIGGER_SEP); |
| return "TRIG_"+parts[0]+"__"+parts[1]; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<Transition> getOutgoingTransitions(StateGraphNode node) { |
| NodeData data = node2data.get(node); |
| if (data==null) |
| return new BasicEList<Transition>(); |
| else |
| return new BasicEList<Transition>(data.getOutTrans()); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<Transition> getIncomingTransitions(StateGraphNode node) { |
| NodeData data = node2data.get(node); |
| if (data==null) |
| return new BasicEList<Transition>(); |
| else |
| return new BasicEList<Transition>(data.getInTrans()); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<ActiveTrigger> getActiveTriggers(State state) { |
| LinkedList<ActiveTrigger> triggers = state2triggers.get(state); |
| if (triggers==null) |
| return new BasicEList<ActiveTrigger>(); |
| else |
| return new BasicEList<ActiveTrigger>(triggers); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<MessageFromIf> getTriggers() { |
| return new BasicEList<MessageFromIf>(triggerstring2mif.values()); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<MessageFromIf> getOwnTriggers() { |
| BasicEList<MessageFromIf> result = new BasicEList<MessageFromIf>(); |
| |
| EList<AbstractInterfaceItem> ownIfItems = getOwnInterfaceItems(getModelComponent()); |
| |
| for(MessageFromIf mif : triggerstring2mif.values()) { |
| if (ownIfItems.contains(mif.getFrom())) |
| result.add(mif); |
| } |
| |
| Collections.sort(result, new Comparator<MessageFromIf>() { |
| |
| @Override |
| public int compare(MessageFromIf o1, MessageFromIf o2) { |
| return getTriggerCodeName(o1).compareTo(getTriggerCodeName(o2)); |
| } |
| |
| |
| }); |
| |
| return result; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public String getMessageID(MessageFromIf mif) { |
| // to be implemented by derived class |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public TransitionChain getChain(Transition trans) { |
| if (trans==null) |
| return null; |
| |
| TransitionChainBundle tcb = trans2chainBundle.get(trans); |
| if (tcb==null || tcb.chains.isEmpty()) |
| return null; |
| |
| return tcb.chains.get(0); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<TransitionChain> getChains(Transition trans) { |
| TransitionChainBundle tcb = trans2chainBundle.get(trans); |
| if(tcb == null) |
| new BasicEList<TransitionChain>(); |
| |
| return tcb.chains; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EObject getData(Transition trans) { |
| if (trans==null) |
| return null; |
| |
| TransitionChainBundle tcb = trans2chainBundle.get(trans); |
| if (tcb==null || tcb.chains.isEmpty()) |
| return null; |
| |
| if (tcb.chains.size()==1) |
| return tcb.chains.get(0).getData(); |
| |
| return tcb.commonData; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<EObject> getIncomingMessages(AbstractInterfaceItem ifitem) { |
| return ifitem.getAllIncomingAbstractMessages(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public TransitionChain addTransitionChain(Transition t) { |
| TransitionChain tc = FsmGenFactory.eINSTANCE.createTransitionChain(); |
| tc.setTransition(t); |
| |
| collectChainTransitions(tc, t); |
| |
| trchains.add(tc); |
| |
| return tc; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<TransitionChain> getTransitionChains() { |
| return new BasicEList<TransitionChain>(trchains); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<TransitionChain> getOwnTransitionChains() { |
| BasicEList<TransitionChain> result = new BasicEList<TransitionChain>(); |
| |
| for (TransitionChain tc : trchains) { |
| if (!targetsOfRefinedTransitions.contains(tc.getTransition()) && isOwnObject(tc.getTransition())) |
| result.add(tc); |
| } |
| |
| Collections.sort(result, new Comparator<TransitionChain>() { |
| |
| @Override |
| public int compare(TransitionChain o1, TransitionChain o2) { |
| return fsmNameProvider.getFullPath(o1.getTransition()).compareTo(fsmNameProvider.getFullPath(o2.getTransition())); |
| } |
| |
| }); |
| |
| return result; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<AbstractInterfaceItem> getOwnInterfaceItems(ModelComponent mc) { |
| return mc.getAbstractInterfaceItems(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EList<AbstractInterfaceItem> getAllInterfaceItems() { |
| return getModelComponent().getAllAbstractInterfaceItems(); |
| } |
| |
| private StateGraphNode getAdjustedTargetNode(Transition t) { |
| StateGraphNode node = fsmHelpers.getNode(t.getTo()); |
| if (node instanceof EntryPoint) { |
| NodeData data = node2data.get(node); |
| if (data==null || data.getOutTrans().isEmpty()) { |
| if (getModelComponent(node).isAbstract()) { |
| if (node.eContainer().eContainer() instanceof State) { |
| // in this case |
| State newTarget = (State) node.eContainer().eContainer(); |
| |
| StateTerminal st = FSMFactory.eINSTANCE.createStateTerminal(); |
| st.setState(newTarget); |
| t.setTo(st); |
| |
| node = newTarget; |
| } |
| } |
| } |
| } |
| return node; |
| } |
| |
| private ModelComponent getModelComponent(EObject node) { |
| node = copy2orig.get(node); |
| while (node!=null) { |
| if (node instanceof ModelComponent) |
| return (ModelComponent) node; |
| node = node.eContainer(); |
| } |
| return null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public boolean isMatching(Trigger trig, String trigstr) { |
| for (MessageFromIf mifp2 : trig.getMsgFromIfPairs()) { |
| String tr2 = getTriggerString(mifp2); |
| if (tr2.equals(trigstr)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public ContinuationTransition getDefaultBranch(EList<Transition> out) { |
| return getDefaultBranch((List<Transition>)out); |
| } |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public EObject getOrig(EObject copy) { |
| return copy2orig.get(copy); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated NOT |
| */ |
| public String getModelComponentName() { |
| return getModelComponent().getComponentName(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
| switch (featureID) { |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE: |
| return basicSetStateMachine(null, msgs); |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__TRANSITION_CHAINS: |
| return ((InternalEList<?>)getTransitionChains()).basicRemove(otherEnd, msgs); |
| } |
| return super.eInverseRemove(otherEnd, featureID, msgs); |
| } |
| |
| private ContinuationTransition getDefaultBranch(List<Transition> out) { |
| for (Transition t : out) { |
| if (t instanceof ContinuationTransition) |
| return (ContinuationTransition) t; |
| } |
| return null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) { |
| switch (featureID) { |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT: |
| if (resolve) return getModelComponent(); |
| return basicGetModelComponent(); |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE: |
| return getStateMachine(); |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__TRANSITION_CHAINS: |
| return getTransitionChains(); |
| } |
| 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 FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT: |
| setModelComponent((ModelComponent)newValue); |
| return; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE: |
| setStateMachine((StateGraph)newValue); |
| return; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__TRANSITION_CHAINS: |
| getTransitionChains().clear(); |
| getTransitionChains().addAll((Collection<? extends TransitionChain>)newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) { |
| switch (featureID) { |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT: |
| setModelComponent((ModelComponent)null); |
| return; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE: |
| setStateMachine((StateGraph)null); |
| return; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__TRANSITION_CHAINS: |
| getTransitionChains().clear(); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) { |
| switch (featureID) { |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__MODEL_COMPONENT: |
| return modelComponent != null; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__STATE_MACHINE: |
| return stateMachine != null; |
| case FsmGenPackage.EXPANDED_MODEL_COMPONENT__TRANSITION_CHAINS: |
| return transitionChains != null && !transitionChains.isEmpty(); |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| } //ExpandedModelComponentImpl |