/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.net.utils; /** * SimpleStateMachine provides a minimal, synchronous state machine framework. * *

This state machine is of limited functionality, but sufficient for implementation of simple * protocols. Due to the limited functionality, it is also easy to read and maintain. * * SimpleStateMachine defaults to the null state. Implementers should immediately transition * to their default state when instantiated. * * @param The input message type. * @param The result type. For SimpleStateMachines without a return value, use {@link * java.lang.Void} */ public abstract class SimpleStateMachine { protected final SimpleState mNullState = new SimpleState() { public R process(T msg) { throw new IllegalStateException("Process called on null state"); } }; protected SimpleState mState = mNullState; // Non-static to allow for compiler verification of T, R from SimpleStateMachine protected abstract class SimpleState { public abstract R process(T msg); } /** * Processes the given message based on the current {@link SimpleState} * * @param msg The message to be processed by the current state * @return The result of the processing by the current state */ public R process(T msg) { return mState.process(msg); } /** * Transitions to a new state * * @param newState The {@link SimpleState} that the {@link SimpleStateMachine} should * transition to * @throws IllegalArgumentException if newState is null */ protected void transitionTo(SimpleState newState) { if (newState == null) { throw new IllegalArgumentException("SimpleState value must be non-null."); } mState = newState; } /** * Transitions to a new state, and lets the new state process the given message * * @param newState The {@link SimpleState} that the {@link SimpleStateMachine} should transition * to. This state will immediately be requested to process the given message. * @param msg The message that should be processed by the new state * @return The result of the processing by the new state * @throws IllegalArgumentException if newState is null */ protected R transitionAndProcess(SimpleState newState, T msg) { transitionTo(newState); return mState.process(msg); } }