use of org.jivesoftware.smack.fsm.StateTransitionResult in project Smack by igniterealtime.
the class ModularXmppClientToServerConnection method attemptEnterState.
/**
* Attempt to enter a state. Note that this method may return <code>null</code> if this state can be safely ignored.
*
* @param successorStateVertex the successor state vertex.
* @param walkStateGraphContext the "walk state graph" context.
* @return A state transition result or <code>null</code> if this state can be ignored.
* @throws SmackException if Smack detected an exceptional situation.
* @throws XMPPException if an XMPP protocol error was received.
* @throws IOException if an I/O error occurred.
* @throws InterruptedException if the calling thread was interrupted.
*/
private StateTransitionResult attemptEnterState(GraphVertex<State> successorStateVertex, WalkStateGraphContext walkStateGraphContext) throws SmackException, XMPPException, IOException, InterruptedException {
final GraphVertex<State> initialStateVertex = currentStateVertex;
final State initialState = initialStateVertex.getElement();
final State successorState = successorStateVertex.getElement();
final StateDescriptor successorStateDescriptor = successorState.getStateDescriptor();
if (!successorStateDescriptor.isMultiVisitState() && walkStateGraphContext.stateAlreadyVisited(successorState)) {
// 'Compression' state. We return 'null' here to signal that the state can safely be ignored.
return null;
}
if (successorStateDescriptor.isNotImplemented()) {
StateTransitionResult.TransitionImpossibleBecauseNotImplemented transtionImpossibleBecauseNotImplemented = new StateTransitionResult.TransitionImpossibleBecauseNotImplemented(successorStateDescriptor);
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState, successorState, transtionImpossibleBecauseNotImplemented));
return transtionImpossibleBecauseNotImplemented;
}
final StateTransitionResult.AttemptResult transitionAttemptResult;
try {
StateTransitionResult.TransitionImpossible transitionImpossible = successorState.isTransitionToPossible(walkStateGraphContext);
if (transitionImpossible != null) {
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState, successorState, transitionImpossible));
return transitionImpossible;
}
invokeConnectionStateMachineListener(new ConnectionStateEvent.AboutToTransitionInto(initialState, successorState));
transitionAttemptResult = successorState.transitionInto(walkStateGraphContext);
} catch (SmackException | IOException | InterruptedException | XMPPException e) {
// Unwind the state here too, since this state will not be unwound by walkStateGraph(), as it will not
// become a predecessor state in the walk.
unwindState(successorState);
throw e;
}
if (transitionAttemptResult instanceof StateTransitionResult.Failure) {
StateTransitionResult.Failure transitionFailureResult = (StateTransitionResult.Failure) transitionAttemptResult;
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionFailed(initialState, successorState, transitionFailureResult));
return transitionAttemptResult;
}
// If transitionAttemptResult is not an instance of TransitionFailureResult, then it has to be of type
// TransitionSuccessResult.
StateTransitionResult.Success transitionSuccessResult = (StateTransitionResult.Success) transitionAttemptResult;
currentStateVertex = successorStateVertex;
invokeConnectionStateMachineListener(new ConnectionStateEvent.SuccessfullyTransitionedInto(successorState, transitionSuccessResult));
return transitionSuccessResult;
}
use of org.jivesoftware.smack.fsm.StateTransitionResult in project Smack by igniterealtime.
the class ModularXmppClientToServerConnection method walkStateGraphInternal.
private void walkStateGraphInternal(WalkStateGraphContext walkStateGraphContext) throws IOException, SmackException, InterruptedException, XMPPException {
// Save a copy of the current state
final GraphVertex<State> initialStateVertex = currentStateVertex;
final State initialState = initialStateVertex.getElement();
final StateDescriptor initialStateDescriptor = initialState.getStateDescriptor();
walkStateGraphContext.recordWalkTo(initialState);
// Check if this is the walk's final state.
if (walkStateGraphContext.isWalksFinalState(initialStateDescriptor)) {
// If this is used as final state, then it should be marked as such.
assert initialStateDescriptor.isFinalState();
// We reached the final state.
invokeConnectionStateMachineListener(new ConnectionStateEvent.FinalStateReached(initialState));
return;
}
List<GraphVertex<State>> outgoingStateEdges = initialStateVertex.getOutgoingEdges();
// See if we need to handle mandatory intermediate states.
GraphVertex<State> mandatoryIntermediateStateVertex = walkStateGraphContext.maybeReturnMandatoryImmediateState(outgoingStateEdges);
if (mandatoryIntermediateStateVertex != null) {
StateTransitionResult reason = attemptEnterState(mandatoryIntermediateStateVertex, walkStateGraphContext);
if (reason instanceof StateTransitionResult.Success) {
walkStateGraph(walkStateGraphContext);
return;
}
// We could not enter a mandatory intermediate state. Throw here.
throw new StateMachineException.SmackMandatoryStateFailedException(mandatoryIntermediateStateVertex.getElement(), reason);
}
for (Iterator<GraphVertex<State>> it = outgoingStateEdges.iterator(); it.hasNext(); ) {
GraphVertex<State> successorStateVertex = it.next();
State successorState = successorStateVertex.getElement();
// state.
if (walkStateGraphContext.wouldCauseCycle(successorStateVertex)) {
// Ignore this successor.
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionIgnoredDueCycle(initialStateVertex, successorStateVertex));
} else {
StateTransitionResult result = attemptEnterState(successorStateVertex, walkStateGraphContext);
if (result instanceof StateTransitionResult.Success) {
break;
}
// record it.
if (result != null) {
walkStateGraphContext.recordFailedState(successorState, result);
}
}
if (!it.hasNext()) {
throw StateMachineException.SmackStateGraphDeadEndException.from(walkStateGraphContext, initialStateVertex);
}
}
// Walk the state graph by recursion.
walkStateGraph(walkStateGraphContext);
}
Aggregations