blob: 0a0d795b1d0b9a1bf2f8163c5f594d032309a37f [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2016 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Jeremie Tatibouet (CEA LIST)
*
*****************************************************************************/
package org.eclipse.papyrus.moka.pssm.statemachines;
import java.util.Iterator;
import org.eclipse.papyrus.moka.fuml.commonbehavior.IEventOccurrence;
import org.eclipse.uml2.uml.State;
public abstract class HistoryPseudostateActivation extends PseudostateActivation implements IHistoryPseudostateActivation{
public boolean hasDefaultTransition(){
// Determine if the history pseudo-state activation has default transition.
// Returns true if it has one, false otherwise
boolean defaultTransition = false;
if(this.outgoingTransitionActivations.size()==1){
defaultTransition = true;
}
return defaultTransition;
}
@Override
public void enter(ITransitionActivation enteringTransition, IEventOccurrence eventOccurrence, IRegionActivation leastCommonAncestor) {
// When entering an history pseudo-state two distinct situations can occur:
// 1. The region has no history and the history pseudo-state has no default
// transition to force entry of a particular vertex. In such situation
// there is no other possibility than to perform a default entry for the
// state hierarchy in which the history pseudo-state is nested. Note that
// if the pseudo-state is placed directly in a region owned by the state
// machine then the region in which it is placed performs a default entry.
// 2. The region already has an history or at least has a default transition
// to force entry to in a particular vertex. In such situation, the state
// hierarchy of the parent state of the history pseudo-state is entered.
// Next the containing state is restored (the result of the restoration
// process is dependent of the type of the history). Note that if the history
// is placed in a region directly owned by the state-machine then the
// restoration process starts from the region.
IVertexActivation parentVertexActivation = this.getParentVertexActivation();
if(parentVertexActivation != null){
IRegionActivation owningRegionActivation = this.getOwningRegionActivation();
if(owningRegionActivation.getHistory() == null && !this.hasDefaultTransition()){
super.enter(enteringTransition, eventOccurrence, leastCommonAncestor);
}else{
parentVertexActivation = (IStateActivation) parentVertexActivation;
parentVertexActivation.setStatus(StateMetadata.ACTIVE);
super.enter(enteringTransition, eventOccurrence, leastCommonAncestor);
this.restore((IStateActivation)parentVertexActivation, enteringTransition, eventOccurrence);
}
}else{
IRegionActivation owningRegionActivation = this.getOwningRegionActivation();
if(owningRegionActivation.getHistory() == null && !this.hasDefaultTransition()){
owningRegionActivation.enter(enteringTransition, eventOccurrence);
}else{
this.restore(owningRegionActivation, enteringTransition, eventOccurrence);
}
}
if(this.isActive()){
this.exit(null, null, null);
}
}
public void restore(IStateActivation stateActivation, ITransitionActivation enteringTransition, IEventOccurrence eventOccurrence){
// Restore the state. Restoring a state consists in :
// 1. Registering the state to the state-machine configuration
// 2. Complete the state if needs to be completed
// 3. If the state cannot be completed then execute its entry and its doActivity. Finally,
// if it has regions then these regions are restored (in parallel).
State state = (State) stateActivation.getNode();
stateActivation.setStatus(StateMetadata.ACTIVE);
IStateMachineExecution smExecution = (IStateMachineExecution)this.getStateMachineExecution();
smExecution.getConfiguration().register(stateActivation);
stateActivation.setEntryCompletion(state.getEntry() == null);
stateActivation.setDoActivityCompletion(state.getDoActivity() == null);
stateActivation.setExitCompletion(state.getExit() == null);
if(stateActivation.hasCompleted()){
stateActivation.complete();
}else{
stateActivation.tryExecuteEntry(eventOccurrence);
stateActivation.tryInvokeDoActivity(eventOccurrence);
for(Iterator<IRegionActivation> regionActivationsIterator = stateActivation.getRegionActivation().iterator(); regionActivationsIterator.hasNext();){
this.restore(regionActivationsIterator.next(), enteringTransition, eventOccurrence);
}
}
}
public abstract void restore(IRegionActivation regionActivation, ITransitionActivation enteringTransition, IEventOccurrence eventOccurrence);
}