/**
* <copyright>
* </copyright>
*
* $Id$
*/
package org.eclipse.etrice.generator.etricegen.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.EObjectImpl;
import org.eclipse.etrice.core.room.State;
import org.eclipse.etrice.core.room.TriggeredTransition;
import org.eclipse.etrice.generator.etricegen.ETriceGenPackage;
import org.eclipse.etrice.core.naming.RoomNameProvider;
import org.eclipse.etrice.core.room.CPBranchTransition;
import org.eclipse.etrice.core.room.ChoicePoint;
import org.eclipse.etrice.core.room.ContinuationTransition;
import org.eclipse.etrice.core.room.EntryPoint;
import org.eclipse.etrice.core.room.ExitPoint;
import org.eclipse.etrice.core.room.NonInitialTransition;
import org.eclipse.etrice.core.room.StateGraphNode;
import org.eclipse.etrice.core.room.SubStateTrPointTerminal;
import org.eclipse.etrice.core.room.TrPoint;
import org.eclipse.etrice.core.room.TrPointTerminal;
import org.eclipse.etrice.core.room.Transition;
import org.eclipse.etrice.core.room.TransitionPoint;
import org.eclipse.etrice.generator.etricegen.ExpandedActorClass;
import org.eclipse.etrice.generator.etricegen.ITransitionChainVisitor;
import org.eclipse.etrice.generator.etricegen.TransitionChain;
/**
* <!-- 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.generator.etricegen.impl.TransitionChainImpl#getTransition <em>Transition</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class TransitionChainImpl extends EObjectImpl implements TransitionChain {
/**
* The cached value of the '{@link #getTransition() <em>Transition</em>}' reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTransition()
* @generated
* @ordered
*/
protected Transition transition;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected TransitionChainImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return ETriceGenPackage.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, ETriceGenPackage.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, ETriceGenPackage.TRANSITION_CHAIN__TRANSITION, oldTransition, transition));
}
/**
* <!-- 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 TriggeredTransition))
return false;
TriggeredTransition trans = (TriggeredTransition)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)
return ((TransitionPoint)tp).isHandler();
}
return false;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String genExecuteChain(ITransitionChainVisitor tcv) {
ExpandedActorClass ac = getExpandedActorClass();
StringBuilder result = new StringBuilder();
result.append(tcv.genTypedData());
genChainCode(getTransition(), ac, tcv, result);
return result.toString();
}
private void genChainCode(Transition tr,
ExpandedActorClass ac, ITransitionChainVisitor tcv, StringBuilder result) {
result.append(tcv.genActionOperationCall(tr));
StateGraphNode node = ac.getNode(tr.getTo());
EList<Transition> out = ac.getOutgoingTransitions(node);
if (node instanceof ChoicePoint) {
ContinuationTransition dflt = ac.getDefaultBranch(out);
assert(dflt!=null): "ChoicePoint "+RoomNameProvider.getFullPath(node)+" has no default branch!";
// generate if/else
for (Transition cond : out) {
if (cond==dflt)
continue;
assert(cond instanceof CPBranchTransition): "The non default ChoicePoint branch "
+RoomNameProvider.getFullPath(cond)+" must be of type CPBranchTransition!";
result.append(tcv.genElseIfBranch((CPBranchTransition)cond));
genChainCode(cond, ac, tcv, result);
}
// generate default
result.append(tcv.genElseBranch(dflt));
genChainCode(dflt, ac, tcv, result);
result.append(tcv.genEndIf());
}
else {
if (node instanceof TrPoint) {
assert(out.size()<=1): "TrPoint "+RoomNameProvider.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 && ac.isOwnObject(state) && state.getEntryCode()!=null && !state.getEntryCode().getCommands().isEmpty())
result.append(tcv.genEntryOperationCall(state));
}
else if (node instanceof ExitPoint) {
if (state!=null && ac.isOwnObject(state) && state.getExitCode()!=null && !state.getExitCode().getCommands().isEmpty())
result.append(tcv.genExitOperationCall(state));
}
else if (node instanceof TransitionPoint) {
if (node==ac.getNode(((NonInitialTransition)tr).getFrom())) {
result.append(tcv.genReturnState(getStateContext()));
return;
}
}
else {
assert(false): "unexpected sub type";
}
genChainCode(out.get(0), ac, 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));
}
}
}
private ExpandedActorClass getExpandedActorClass() {
EObject obj = getTransition();
while (obj!=null) {
obj = obj.eContainer();
if (obj instanceof ExpandedActorClass)
return (ExpandedActorClass) obj;
}
return null;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case ETriceGenPackage.TRANSITION_CHAIN__TRANSITION:
if (resolve) return getTransition();
return basicGetTransition();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case ETriceGenPackage.TRANSITION_CHAIN__TRANSITION:
setTransition((Transition)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case ETriceGenPackage.TRANSITION_CHAIN__TRANSITION:
setTransition((Transition)null);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case ETriceGenPackage.TRANSITION_CHAIN__TRANSITION:
return transition != null;
}
return super.eIsSet(featureID);
}
} //TransitionChainImpl