{"id":33180937,"url":"https://github.com/UnquietCode/JState","last_synced_at":"2025-11-20T21:04:41.235Z","repository":{"id":3557263,"uuid":"4618498","full_name":"UnquietCode/JState","owner":"UnquietCode","description":"Advanced state machines in Java.","archived":false,"fork":false,"pushed_at":"2018-11-28T23:03:48.000Z","size":226,"stargazers_count":97,"open_issues_count":3,"forks_count":21,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-07-14T21:36:12.067Z","etag":null,"topics":["finite-state-machine","fsm","java","state-machine"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UnquietCode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-06-10T21:23:30.000Z","updated_at":"2024-03-31T14:12:51.000Z","dependencies_parsed_at":"2022-08-20T09:50:31.202Z","dependency_job_id":null,"html_url":"https://github.com/UnquietCode/JState","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/UnquietCode/JState","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnquietCode%2FJState","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnquietCode%2FJState/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnquietCode%2FJState/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnquietCode%2FJState/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UnquietCode","download_url":"https://codeload.github.com/UnquietCode/JState/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UnquietCode%2FJState/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285512077,"owners_count":27184296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-20T02:00:05.334Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["finite-state-machine","fsm","java","state-machine"],"created_at":"2025-11-16T04:00:23.294Z","updated_at":"2025-11-20T21:04:41.230Z","avatar_url":"https://github.com/UnquietCode.png","language":"Java","readme":"# JState (v3.1) [![Build Status](https://travis-ci.org/UnquietCode/JState.png?branch=master)](https://travis-ci.org/UnquietCode/JState)\nA core Java tool which provides state machine semantics using enums, strings, or anything else you\nwant to represent the various states. States have transitions which can move them to other states.\nCallbacks are provided for transitions, and for each state when entering or exiting. It is also\npossible to route a transition request based on your own logic. You can even provide a callback\nwhich will fire when a sequence of states is matched.\n\nAll of the methods which modify, transition, or inquire about the state are synchronized, allowing\nmultiple threads access to the same state machine. However, to avoid unpredictable behavior, it is\ngenerally better to construct your state machine up front and not modify it thereafter. The\nEnumStateMachine and StringStateMachine in particular can be serialized to and from their string\nrepresentations.\n\nAs of version 3.0, the minimum version of Java required is JDK 8.\n\n# Installation\nThe project is built using Maven, and the artifacts are available from Maven Central. (If you\nare a current user of the tool, note that the group name has been recently changed to\naccommodate Sonatype's repository hosting requirements.)\n```\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.unquietcode.tools.jstate\u003c/groupId\u003e\n    \u003cartifactId\u003ejstate\u003c/artifactId\u003e\n    \u003cversion\u003e3.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n# Documentation\nYou can view the provided [Javadocs](http://www.javadoc.io/doc/com.unquietcode.tools.jstate/jstate/3.1) or the [unit tests](src/test/java/unquietcode/tools/esm) for more information about how to use the library.\n\n# Usage\nA typical use case might be a state machine for controlling a process, which can move between the\nstates [`Ready`, `Running`, `Paused`, `Stopping`, `Stopped`, `Finished`].\n\n![State Diagram](./example-diagram.png)\n\nAfter declaring a state enum we can set up a new state machine as follows:\n\n```java\nenum State {\n    Ready, Running, Paused, Stopping, Stopped, Finished\n}\n\n...\n\nEnumStateMachine\u003cState\u003e esm = new EnumStateMachine\u003c\u003e(State.Ready);\nesm.addTransitions(State.Ready, State.Running, State.Finished);\nesm.addTransitions(State.Running, State.Paused, State.Stopping);\nesm.addTransitions(State.Paused, State.Running, State.Stopping);\nesm.addTransitions(State.Stopping, State.Stopped);\nesm.addTransitions(State.Stopped, State.Finished);\nesm.addTransitions(State.Finished, State.Ready, null);\n\nesm.transition(State.Running);\n```\n\nThe initial state is set either in the constructor or the `setInitialState(...)` method. The `addTransition(...)`\nmethod supports mapping from 1..n states. In the example above, we see that some states can move to more than\none other states. The `null` state is also a possibility, depending on your preference.\n\nCallbacks can be added as transitions are defined, and fire during transition between states:\n```java\nTransitionHandler\u003cState\u003e cb = new TransitionHandler\u003c\u003e() {\n    public void onTransition(State from, State to) {\n        // ....\n    }\n};\n\nesm.addTransitions(cb, State.Ready, State.Running);\n```\n\nCallbacks can also be added on entering or exiting a state.\n```java\nesm.onEntering(State.Running, new StateHandler\u003cState\u003e() {\n\tpublic void onState(State state) {\n\t\tentered.incrementAndGet();\n\t}\n});\n\nesm.onExiting(State.Running, new StateHandler\u003cState\u003e() {\n\tpublic void onState(State state) {\n\t\texited.incrementAndGet();\n\t}\n});\n```\n\n`StateRouters` allow you to 'deflect' or 'redirect' a transition based on your own custom logic.\nThere are several pre-defined routers available which provide round-robin and randomized routing.\n```java\nesm.routeBeforeEntering(TestStates.Three, new StateRouter\u003cTestStates\u003e() {\n\tpublic TestStates route(TestStates current, TestStates next) {\n\t\treturn TestStates.Two;\n\t}\n});\n```\n\n`SequenceHandlers` are callbacks which are triggered whenever the specified sequence of states\noccurs in the state machine.\n```java\nfinal List\u003cColor\u003e _pattern = Arrays.asList(Color.Blue, Color.Green, Color.Orange);\n\nsm.onSequence(_pattern, new SequenceHandler\u003cColor\u003e() {\n\tpublic void onMatch(List\u003cColor\u003e pattern) {\n\t\t// pattern equals [Blue, Green, Orange]\n\t}\n});\n```\n\nThere is also support for wildcard matching in sequences, available through the use\nof the `PatternBuilder` class.\n```java\nfinal Pattern\u003cColor\u003e _pattern = PatternBuilder.\u003cColor\u003ecreate()\n\t.add(Color.Red, Color.Blue)\n\t.addWildcard()\n\t.add(Color.Green)\n.build();\n\nsm.onSequence(_pattern, new SequenceHandler\u003cColor\u003e() {\n\tpublic void onMatch(List\u003cColor\u003e pattern) {\n\t\t// pattern equals [Red, Blue, Purple, Green]\n\t}\n});\n```\n\nA special form of `StringStateMachine` (which uses strings as states) is available as the `ReflectiveStateMachine`.\nThis flavor allows you to declare your callbacks as methods of the state machine class. The arguments are flexible, matching the standalone callback\nmethod's signature and allowing you to skip parameters you don't care about.\n```java\nReflectiveStateMachine sm = new ReflectiveStateMachine() {\n\n\t// (optional method to declare transitions inline)\n\tprotected void declareTransitions() {\n\t\taddTransition(null, \"blue\");\n\t\taddTransition(\"blue\", \"green\");\n\t\taddTransition(\"green\", null);\n\t}\n\n\tpublic void onEnteringBlue(String state) {\n\t\tenteringBlue.incrementAndGet();\n\t}\n\n\tpublic void onExitingBlue() {\n\t\texitingBlue.incrementAndGet();\n\t}\n\n\tpublic void onGreen() {\n\t\tenteringGreen.incrementAndGet();\n\t}\n\n\tpublic void onEntering() {\n\t\tenteringAny.incrementAndGet();\n\t}\n\n\tpublic void onExiting() {\n\t\texitingAny.incrementAndGet();\n\t}\n\n\tpublic void onTransition() {\n\t\ttransitionAny.incrementAndGet();\n\t}\n};\n\nsm.transition(\"blue\");\nsm.transition(\"green\");\nsm.transition(null);\n```\n\n\nSee the [tests](src/test/java/unquietcode/tools/esm) for more usage examples.\n\n# License\nJState is licensed under the MIT license. Go wild.\n\n# Questions / Comments / Feedback\nSend an email to blouis@unquietcode.com\n  \nPeace, love, and code.\n\n# Thanks!\n","funding_links":[],"categories":["Libraries"],"sub_categories":["Java"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FUnquietCode%2FJState","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FUnquietCode%2FJState","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FUnquietCode%2FJState/lists"}