jeudi 6 août 2020

Self Running to completion state machine with Enums in Java

During development I needed to design a state machine with decision which runs to completion and performs state transition without the need to wait for events. So i come up with the following implementation that I want to share.

So the state machine is described with the following Enum

public enum PnoBarringState {
  OPERATOR_WHITE_LIST_START {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        if (commonMethods.isMatchingOperatorsWhiteList(sessionData, pnoValue)) {
            return GROUP_WHITE_LIST;
        } else {
            return OPERATOR_BLACK_LIST;
        }
    }
  },
  GROUP_WHITE_LIST {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        if (commonMethods.isMatchingGroupsWhiteList(sessionData, pnoValue)) {
            return PNO_CHECK_FINISHED;
        } else {
            return GROUP_BLACK_LIST;
        }
    }
  },
  OPERATOR_BLACK_LIST {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        if (commonMethods.isMatchingOperatorsBlackList(sessionData, pnoValue)) {
            return PNO_FORBIDDEN_NUMBER_OPERATOR_LEVEL;
        } else {
            return GROUP_WHITE_LIST;
        }
    }
  },
  GROUP_BLACK_LIST {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        if (commonMethods.isMatchingGroupsBlackList(sessionData, pnoValue))
            return PNO_FORBIDDEN_NUMBER_GROUP_LEVEL;
        else {
            return PNO_CHECK_FINISHED;
        }
    }
  },
  PNO_CHECK_FINISHED {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        return this;
    }

    @Override
    public boolean hasNext() {
        return false;
    }
  },
  PNO_FORBIDDEN_NUMBER_OPERATOR_LEVEL {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        throw new CustomUncheckedException( "Operator Level Barring");
    }
  },
  PNO_FORBIDDEN_NUMBER_GROUP_LEVEL {
    @Override
    public PnoBarringState nextState(SessionData sessionData, String pnoValue) {
        throw new CustomUncheckedException("Group Level Barring");
    }
  };

  public abstract PnoBarringState nextState(SessionData sessionData, String pnoValue);

  public boolean hasNext() { return true; }
}

Function "nextState()" is abstract and implemented in each state in order to examine the transition and return to a new state. Only the "END" state is returning to the same state. Since it is also desinged to be used in a run-to-completation a "hasNext()" function is provided. The "END" state is overwritting so as to declare the finish of the state-machine.

This enum is then used inside a normal application code with the following way.

PnoBarringState pnoBarringState = PnoBarringState.OPERATOR_WHITE_LIST_START;

while (pnoBarringState.hasNext()) {
    pnoBarringState = pnoBarringState.nextState(sessionData, pnoValue);
}

I am not sure whether any pattern describes it in the same way but i was feeling like sharing it. Any other approaches are considered valuable.

Aucun commentaire:

Enregistrer un commentaire