blob: b54eb5b3a382a56d185825fac578b000ae576393 [file] [log] [blame]
/*******************************************************************************
* 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 org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.ExpandedModelComponent;
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.FsmGenPackage;
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.ITransitionChainVisitor;
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.TransitionChain;
import org.eclipse.etrice.core.fsm.fSM.CPBranchTransition;
import org.eclipse.etrice.core.fsm.fSM.ChoicePoint;
import org.eclipse.etrice.core.fsm.fSM.ContinuationTransition;
import org.eclipse.etrice.core.fsm.fSM.EntryPoint;
import org.eclipse.etrice.core.fsm.fSM.ExitPoint;
import org.eclipse.etrice.core.fsm.fSM.State;
import org.eclipse.etrice.core.fsm.fSM.StateGraphNode;
import org.eclipse.etrice.core.fsm.fSM.SubStateTrPointTerminal;
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.TransitionChainStartTransition;
import org.eclipse.etrice.core.fsm.fSM.TransitionPoint;
import org.eclipse.etrice.core.fsm.naming.FSMNameProvider;
import org.eclipse.etrice.core.fsm.util.FSMHelpers;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Transition Chain</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl.TransitionChainImpl#getTransition <em>Transition</em>}</li>
* <li>{@link org.eclipse.etrice.core.genmodel.fsm.fsmgen.impl.TransitionChainImpl#getData <em>Data</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class TransitionChainImpl extends MinimalEObjectImpl.Container implements TransitionChain {
private FSMHelpers fsmHelpers = new FSMHelpers();
private FSMNameProvider fsmNameProvider = new FSMNameProvider();
/**
* The cached value of the '{@link #getTransition() <em>Transition</em>}' reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTransition()
* @generated
* @ordered
*/
protected Transition transition;
/**
* The cached value of the '{@link #getData() <em>Data</em>}' reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getData()
* @generated
* @ordered
*/
protected EObject data;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected TransitionChainImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return FsmGenPackage.Literals.TRANSITION_CHAIN;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Transition getTransition() {
if (transition != null && transition.eIsProxy()) {
InternalEObject oldTransition = (InternalEObject)transition;
transition = (Transition)eResolveProxy(oldTransition);
if (transition != oldTransition) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, FsmGenPackage.TRANSITION_CHAIN__TRANSITION, oldTransition, transition));
}
}
return transition;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Transition basicGetTransition() {
return transition;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTransition(Transition newTransition) {
Transition oldTransition = transition;
transition = newTransition;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, FsmGenPackage.TRANSITION_CHAIN__TRANSITION, oldTransition, transition));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EObject getData() {
if (data != null && data.eIsProxy()) {
InternalEObject oldData = (InternalEObject)data;
data = eResolveProxy(oldData);
if (data != oldData) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, FsmGenPackage.TRANSITION_CHAIN__DATA, oldData, data));
}
}
return data;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EObject basicGetData() {
return data;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setData(EObject newData) {
EObject oldData = data;
data = newData;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, FsmGenPackage.TRANSITION_CHAIN__DATA, oldData, data));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public State getStateContext() {
if (getTransition().eContainer().eContainer() instanceof State)
return (State) getTransition().eContainer().eContainer();
return null;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public boolean isHandler() {
if (getTransition() instanceof TransitionChainStartTransition) {
TransitionChainStartTransition trans = (TransitionChainStartTransition)getTransition();
if (trans.getFrom() instanceof TrPointTerminal) {
TrPoint tp = ((TrPointTerminal)trans.getFrom()).getTrPoint();
if (tp instanceof TransitionPoint)
return ((TransitionPoint)tp).isHandler();
}
else if (trans.getFrom() instanceof SubStateTrPointTerminal) {
TrPoint tp = ((SubStateTrPointTerminal)trans.getFrom()).getTrPoint();
if (tp instanceof TransitionPoint)
assert(false): "not allowed to connect TransitionPoint to exterior";
}
}
return false;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String genExecuteChain(ITransitionChainVisitor tcv) {
ExpandedModelComponent emc = getExpandedModelComponent();
StringBuilder result = new StringBuilder();
/* TODO: the next generated code declares a correctly typed variable for the generic data.
* It is hard to determine whether it is actually needed though.
* It is needed in non-initial transitions with action code that are not data driven.
* It might be needed in condition expressions. But this code would have to be parsed
* with uncertain result (because of e.g. comments).
*/
result.append(tcv.genTypedData(this));
genChainCode(getTransition(), emc, tcv, result);
return result.toString();
}
private void genChainCode(Transition tr,
ExpandedModelComponent emc, ITransitionChainVisitor tcv, StringBuilder result) {
result.append(tcv.genActionOperationCall(tr));
StateGraphNode node = fsmHelpers.getNode(tr.getTo());
EList<Transition> out = emc.getOutgoingTransitions(node);
if (node instanceof ChoicePoint) {
ContinuationTransition dflt = emc.getDefaultBranch(out);
assert(dflt!=null): "ChoicePoint "+fsmNameProvider.getFullPath(node)+" has no default branch!";
// generate if/else
boolean isFirst = true;
for (Transition cond : out) {
if (cond==dflt)
continue;
assert(cond instanceof CPBranchTransition): "The non default ChoicePoint branch "
+fsmNameProvider.getFullPath(cond)+" must be of type CPBranchTransition!";
result.append(tcv.genElseIfBranch((CPBranchTransition)cond, isFirst));
isFirst = false;
genChainCode(cond, emc, tcv, result);
}
// generate default
result.append(tcv.genElseBranch(dflt));
genChainCode(dflt, emc, tcv, result);
result.append(tcv.genEndIf());
}
else {
if (node instanceof TrPoint) {
if (node instanceof TransitionPoint) {
// TransitionPoint is final destination of the chain
result.append(tcv.genReturnState(getStateContext(), false));
return;
}
else {
assert(out.size()<=1): "TrPoint "+fsmNameProvider.getFullPath(node)
+" is expected to have at most one outgoing transition!";
if (out.size()==1) {
State state = (node.eContainer().eContainer() instanceof State)? (State)node.eContainer().eContainer():null;
if (node instanceof EntryPoint) {
if (state!=null && emc.isOwnObject(state) && state.getEntryCode()!=null && !state.getEntryCode().getLines().isEmpty())
result.append(tcv.genEntryOperationCall(state));
}
else if (node instanceof ExitPoint) {
if (state!=null && emc.isOwnObject(state) && state.getExitCode()!=null && !state.getExitCode().getLines().isEmpty())
result.append(tcv.genExitOperationCall(state));
}
else {
assert(false): "unexpected sub type";
}
}
}
genChainCode(out.get(0), emc, tcv, result);
}
else {
// the following assertion should always hold true
assert(node instanceof State): "A transition target can be a ChoicePoint, a TrPoint or a State!";
result.append(tcv.genReturnState((State) node, true));
}
}
}
private ExpandedModelComponent getExpandedModelComponent() {
EObject obj = getTransition();
while (obj!=null) {
obj = obj.eContainer();
if (obj instanceof ExpandedModelComponent)
return (ExpandedModelComponent) obj;
}
return null;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case FsmGenPackage.TRANSITION_CHAIN__TRANSITION:
if (resolve) return getTransition();
return basicGetTransition();
case FsmGenPackage.TRANSITION_CHAIN__DATA:
if (resolve) return getData();
return basicGetData();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case FsmGenPackage.TRANSITION_CHAIN__TRANSITION:
setTransition((Transition)newValue);
return;
case FsmGenPackage.TRANSITION_CHAIN__DATA:
setData((EObject)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case FsmGenPackage.TRANSITION_CHAIN__TRANSITION:
setTransition((Transition)null);
return;
case FsmGenPackage.TRANSITION_CHAIN__DATA:
setData((EObject)null);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case FsmGenPackage.TRANSITION_CHAIN__TRANSITION:
return transition != null;
case FsmGenPackage.TRANSITION_CHAIN__DATA:
return data != null;
}
return super.eIsSet(featureID);
}
} //TransitionChainImpl