package
com.zte.liu.statemachine;
import
java.util.ArrayList;
import
java.util.HashMap;
import
com.zte.liu.messagehandler.Handler;
import
com.zte.liu.messagehandler.Looper;
import
com.zte.liu.messagehandler.Message;
import
com.zte.liu.messagehandler.MessageQueue;
public
class
HsmHandler
extends
Handler {
private
HashMap<HierarchicalState, StateInfo> mStateInfo =
new
HashMap<HierarchicalState, StateInfo>();
private
HierarchicalState mInitialState =
null ;
private
HierarchicalState mDestState =
null ;
private
ArrayList<StateInfo> mInitialStateList =
new
ArrayList<StateInfo>();
private
ArrayList<Message> mDeferredMessages =
new
ArrayList<Message>();
public
HsmHandler(Looper looper) {
super (looper);
}
private
class
StateInfo{
HierarchicalState
state;
HierarchicalState
parentState;
boolean
active;
}
public
void
addState(HierarchicalState state, HierarchicalState parentState){
//只在非多线程情况
if (state
== null ){
throw
new
RuntimeException(
"state
cannot be null when adding state." );
}
/*
if(mStateInfo.containsKey(state) && mStateInfo.get(state).parentState!=parentState){
throw
new RuntimeException("we cannot add a state with different parents.");
}
*/
if (mStateInfo.containsKey(state)){
return ;
}
StateInfo
stateInfo = new
StateInfo();
stateInfo.state
= state;
stateInfo.parentState
= parentState;
stateInfo.active
= false ;
mStateInfo.put(state,
stateInfo);
}
public
void
setInitialState(HierarchicalState state){
if (!mStateInfo.containsKey(state)){
throw
new
RuntimeException(
"cannot
set a initial state which is not contained in the build tree." );
}
mInitialState
= state;
}
public
void
completeConstruction(){
if (mInitialState
== null ){
return ;
}
StateInfo
initialStateInfo = mStateInfo.get(mInitialState);
while (initialStateInfo
!= null ){
mInitialStateList.add(initialStateInfo);
if (initialStateInfo.parentState
== null ){
initialStateInfo
= null ;
} else {
initialStateInfo
= mStateInfo.get(initialStateInfo.parentState);
}
}
invokeEnterMethods( null );
performTransitions();
}
public
void
invokeEnterMethods(StateInfo commonStateInfo){
int
start = mInitialStateList.size() -
1 ;
for ( int
i=mInitialStateList.size()-
1 ;
i>= 0 ;
i--){
if (mInitialStateList.get(i)
== commonStateInfo){
start
= i - 1 ;
break ;
}
}
for ( int
i=start; i>=
0 ;
i--){
StateInfo
stateInfo = mInitialStateList.get(i);
stateInfo.state.enter();
stateInfo.active
= true ;
}
}
public
void
invokeExitMethods(StateInfo commonStateInfo){
for ( int
i=
0 ;
i<mInitialStateList.size()- 1 ;
i++){
StateInfo
stateInfo = (StateInfo)mInitialStateList.get(i);
if (stateInfo
!= commonStateInfo){
stateInfo.state.exit();
stateInfo.active
= false ;
} else {
break ;
}
}
}
public
void
performTransitions(){
if (mDestState
== null ){
return ;
}
ArrayList<StateInfo>
tempList = new
ArrayList<StateInfo>();
StateInfo
commonStateInfo = getCommonStateInfo(mDestState, tempList);
invokeExitMethods(commonStateInfo);
refreshInitialStateList(commonStateInfo,
tempList);
invokeEnterMethods(commonStateInfo);
moveDeferredMsgAtFrontQueue();
}
public
void
deferMessage(Message msg){
mDeferredMessages.add(msg);
}
public
void
handleMessage(Message msg){
//重写!!
///////////////////////////////////////
//////////////////////////////////////
}
public
void
transitionTo(HierarchicalState destState){
mDestState
= destState;
}
private
StateInfo getCommonStateInfo(HierarchicalState destState, ArrayList<StateInfo> tempList){
StateInfo
stateInfo = mStateInfo.get(destState);
while (stateInfo!= null
&& stateInfo.active==
false ){
tempList.add(stateInfo);
if (stateInfo.parentState
== null ){
stateInfo
= null ;
} else {
stateInfo
= mStateInfo.get(stateInfo.parentState);
}
}
return
stateInfo;
}
private
void
refreshInitialStateList(StateInfo commonStateInfo, ArrayList<StateInfo> tempList){
for ( int
i=
0 ;
i<mInitialStateList.size()- 1 ;
i++){
if (mInitialStateList.get(i)
!= commonStateInfo){
mInitialStateList.remove(i);
}
}
for ( int
i=tempList.size()-
1 ;
i>= 0 ;
i--){
mInitialStateList.add( 0 ,
tempList.get(i));
}
}
private
void
moveDeferredMsgAtFrontQueue(){
MessageQueue
msgQueue = this .getLooper().getQueue();
for ( int
i=mDeferredMessages.size()-
1 ;
i>= 0 ;
i--){
msgQueue.addToFront(mDeferredMessages.get(i));
}
}
}
|