The GPLS framework currently support two transition types :
The inner class CreateTaskTransition is an operation state transition by extending the abstract OperationStateTransition An transition of this type is triggered by end user performing an operation typically by pushing a button or selecting an meny item, that sort of things. The state transition to be implemented here is the one of creating a new task.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #!/usr/bin/java package org.aha.application.taskmanager.usecases; import static org.aha.application.taskmanager.TaskDoneUtil.updateAfterTaskAddedOrRemoved; import java.util.ResourceBundle; import org.aha.application.taskmanager.data.ITaskRepository; import org.aha.application.taskmanager.usecases.RemoveTaskUseCase.RemoveTaskTransition; import org.aha.commons.ThrowIf; import org.aha.gpls.viewmodel.DataViewModel; import org.aha.gpls.viewmodel.PropertyParameters; import org.aha.gpls.viewmodel.statemachine.OperationStateTransition; import org.aha.gpls.viewmodel.statemachine.UseCase; /** * <p> * Use case for creating a task. * </p> */ public final class CreateTaskUseCase extends UseCase { /** * <p> * Constructor. * </p> * @param rep Interface to persistent task storage. */ public CreateTaskUseCase(ITaskRepository rep) { ThrowIf.isNull("rep", rep); // This use case has a single state transition that creates a task. addOperationTransition(new CreateTaskTransition(rep)); } /** * <p> * {@link OperationStateTransition} that create new task. * </p> */ public static class CreateTaskTransition extends OperationStateTransition { private final ITaskRepository _rep; private CreateTaskTransition(ITaskRepository rep){ _rep=rep; } @Override public void transit(DataViewModel parentTask, ResourceBundle resources) { // In order to make a new task we need parent's id. It is an // integer and it is mandatory for a task to have this property // so ask for a Integer type value explicit and use the // 'mandatory' method which will throw an exception if view model // representing the parent missing id property. Integer pid=parentTask.getMandatoryPropertyValue(Integer.class, "id"); // Having the id of the parent can ask repository to create new // task. Integer sid=_rep.createSubTask(pid); // If we are here new task has been successfully created and we // must update the view model graph to reflect this fact: // First create a view model to represent the new task. DataViewModel subTask=parentTask.createChild(); // Parameter to setProperty methods telling views not to expose // property to end user. PropertyParameters notExposed=new PropertyParameters() .exposed(false); // Sets the property of the new task: // The id property is for code only so third tell views not to // expose this property to end user (default is to expose). subTask.setProperty("id", sid, notExposed); // All tasks has a name property of string type but for a new task // it is unassigned. subTask.setProperty("name", String.class); // All tasks has a boolean property telling if a task is done or // not. A newly created task is 'not done'. subTask.setProperty("done", false); // Tells which operations end user can do related to created task. // Can create a sub task (do what we do here :-) subTask.addOperation(CreateTaskTransition.class); // Can remove it. subTask.addOperation(RemoveTaskTransition.class); // The new task may have changed state of ancestors in hierarchy; // the 'updateAfterTaskAddedOrRemoved' algorithm will do needed // updates. updateAfterTaskAddedOrRemoved(parentTask); } } } |
Implementation of the state transition is to implement the virtual method transit (line 49) that accepts two parameters:
The transit method here does:
State transitions are collected in use cases. In this case the use case (CreateTaskUseCase) consist only of one transition, in general an use case can have several transitions of different types that natural belong together.
The code that configure the application passes an instance of the use case to the state machine that is to drive the application. The use case for creating a task is added to the state machine in the task manager application's main method listed below (line 11).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/java public static void main(String[] args) { ITaskRepository rep=getTaskRepository(); DataViewModel initialState=getInitialState(args, rep); ResourceBundle resources=getResources(args); new PresentationLayer( new StateMachine(initialState) .addUseCase(new CreateTaskUseCase(rep)) .addUseCase(new RemoveTaskUseCase(rep)) .addUseCase(new ChangeTaskDoneStatusUseCase(rep)), resources); } |