1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.net.utils; 18 19 /** 20 * SimpleStateMachine provides a minimal, synchronous state machine framework. 21 * 22 * <p>This state machine is of limited functionality, but sufficient for implementation of simple 23 * protocols. Due to the limited functionality, it is also easy to read and maintain. 24 * 25 * SimpleStateMachine defaults to the null state. Implementers should immediately transition 26 * to their default state when instantiated. 27 * 28 * @param <T> The input message type. 29 * @param <R> The result type. For SimpleStateMachines without a return value, use {@link 30 * java.lang.Void} 31 */ 32 public abstract class SimpleStateMachine<T, R> { 33 protected final SimpleState mNullState = 34 new SimpleState() { 35 public R process(T msg) { 36 throw new IllegalStateException("Process called on null state"); 37 } 38 }; 39 40 protected SimpleState mState = mNullState; 41 42 // Non-static to allow for compiler verification of T, R from SimpleStateMachine 43 protected abstract class SimpleState { process(T msg)44 public abstract R process(T msg); 45 } 46 47 /** 48 * Processes the given message based on the current {@link SimpleState} 49 * 50 * @param msg The message to be processed by the current state 51 * @return The result of the processing by the current state 52 */ process(T msg)53 public R process(T msg) { 54 return mState.process(msg); 55 } 56 57 /** 58 * Transitions to a new state 59 * 60 * @param newState The {@link SimpleState} that the {@link SimpleStateMachine} should 61 * transition to 62 * @throws IllegalArgumentException if newState is null 63 */ transitionTo(SimpleState newState)64 protected void transitionTo(SimpleState newState) { 65 if (newState == null) { 66 throw new IllegalArgumentException("SimpleState value must be non-null."); 67 } 68 69 mState = newState; 70 } 71 72 /** 73 * Transitions to a new state, and lets the new state process the given message 74 * 75 * @param newState The {@link SimpleState} that the {@link SimpleStateMachine} should transition 76 * to. This state will immediately be requested to process the given message. 77 * @param msg The message that should be processed by the new state 78 * @return The result of the processing by the new state 79 * @throws IllegalArgumentException if newState is null 80 */ transitionAndProcess(SimpleState newState, T msg)81 protected R transitionAndProcess(SimpleState newState, T msg) { 82 transitionTo(newState); 83 return mState.process(msg); 84 } 85 } 86