Compare commits

..
2 Commits
Author SHA1 Message Date
0264408andCursor f0ddaf7694 refactor: split public types into definition, runtime, and spi packages
Keep Maven modules unchanged. Hosts import models and SPIs from the new packages; OrdoEngine stays at com.jetlumen.ordo.api.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 11:18:10 +08:00
0264408andCursor d743939964 feat: dispatch NamedAction and NamedCondition by key
Hosts register one bean per action/condition; Spring wires the dispatcher when no facade is defined, and REST catalog projects from those beans.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 11:07:57 +08:00
102 changed files with 907 additions and 302 deletions
+5 -4
View File
@@ -21,14 +21,14 @@
- 线性或多步图:`StepTransition` + 内置谓词 / 宿主 `RoutingCondition` - 线性或多步图:`StepTransition` + 内置谓词 / 宿主 `RoutingCondition`
- 会签/或签:`ApprovalPolicy.ALL` / `ANY`(多候选人) - 会签/或签:`ApprovalPolicy.ALL` / `ANY`(多候选人)
- 结构化并行:`kind: PARALLEL` 块(一层、join ALL) - 结构化并行:`kind: PARALLEL` 块(一层、join ALL)
- ACTION 步骤:事务提交后调用宿主 `ActionHandler` - ACTION 步骤:事务提交后调用宿主 `ActionHandler`(可经 `NamedAction` 分发)
- 发起人撤回:`WITHDRAWN`,待办任务 `SKIPPED` - 发起人撤回:`WITHDRAWN`,待办任务 `SKIPPED`
- 管理员/系统取消:`cancel` → `CANCELLED`,待办任务 `SKIPPED`(引擎不鉴权角色) - 管理员/系统取消:`cancel` → `CANCELLED`,待办任务 `SKIPPED`(引擎不鉴权角色)
- 任务转派:当前办理人 `reassign`,审计 `TASK_REASSIGNED` - 任务转派:当前办理人 `reassign`,审计 `TASK_REASSIGNED`
- 到期升级:步骤 `due` + `processDue`,审计 `TASK_ESCALATED` - 到期升级:步骤 `due` + `processDue`,审计 `TASK_ESCALATED`
- 分页查询:任务 / 实例 / 流程定义 - 分页查询:任务 / 实例 / 流程定义
- 审计时间线:`ProcessEvent` + `queryHistory` - 审计时间线:`ProcessEvent` + `queryHistory`
- 扩展点:`AssigneeResolver`、`RoutingCondition`、`ActionHandler`、`OrdoEventListener` - 扩展点:`AssigneeResolver`、`RoutingCondition`、`ActionHandler`、`NamedCondition`、`NamedAction`、`OrdoEventListener`
开发计划:可选 REST + 目录 SPI。设计器为独立产品(不进本仓库),待 REST 与目录之后。多租户 **暂不在计划中**。见 [docs/roadmap.md](docs/roadmap.md)。 开发计划:可选 REST + 目录 SPI。设计器为独立产品(不进本仓库),待 REST 与目录之后。多租户 **暂不在计划中**。见 [docs/roadmap.md](docs/roadmap.md)。
@@ -112,8 +112,9 @@ ordo:
| Bean | 默认 | | Bean | 默认 |
|---|---| |---|---|
| `AssigneeResolver` | 候选人即办理人 | | `AssigneeResolver` | 候选人即办理人 |
| `RoutingCondition` | 始终匹配(`ref` 边;宿主可按 key+args 分发) | | `NamedCondition` / `NamedAction` | 可多个;无对应门面时按 key 分发 |
| `ActionHandler` | 空操作 | | `RoutingCondition` | 无具名 condition 时始终匹配;有则未知 `ref` 为 false |
| `ActionHandler` | 无具名 action 时空操作;有则未知 key 抛错 |
| `OrdoEventListener` | 可注册多个,提交后按顺序调用 | | `OrdoEventListener` | 可注册多个,提交后按顺序调用 |
## 运行时约定 ## 运行时约定
+1
View File
@@ -19,6 +19,7 @@
- 到期升级 `processDue` / `TASK_ESCALATED` - 到期升级 `processDue` / `TASK_ESCALATED`
- 管理员/系统取消 `cancel` / `CANCELLED` - 管理员/系统取消 `cancel` / `CANCELLED`
- 可选 REST(autoconfigure 条件装配)+ 目录 SPI `OrdoCatalog` - 可选 REST(autoconfigure 条件装配)+ 目录 SPI `OrdoCatalog`
- `NamedAction` / `NamedCondition` 注册与官方 key 分发;默认 Catalog 从具名 Bean 投影
## 开发计划(确定要做) ## 开发计划(确定要做)
+20 -13
View File
@@ -76,12 +76,16 @@ ordo:
| Bean | 默认 | | Bean | 默认 |
|---|---| |---|---|
| `AssigneeResolver` | 候选人字符串即办理人 | | `AssigneeResolver` | 候选人字符串即办理人 |
| `RoutingCondition` | `ref` 边默认恒 true;无 `when` 的边不经过该 Bean | | `NamedCondition` | 可有多个;无 `RoutingCondition` 门面且列表非空时装配 `DispatchingRoutingCondition` |
| `ActionHandler` | 空操作 | | `NamedAction` | 可有多个;无 `ActionHandler` 门面且列表非空时装配 `DispatchingActionHandler` |
| `RoutingCondition` | 无 `NamedCondition` 时 `ref` 边恒 true;有则按 key 分发,未知 `ref` 为 false |
| `ActionHandler` | 无 `NamedAction` 时空操作;有则按 key 分发,未知 key 抛 `IllegalArgumentException` |
| `OrdoEventListener` | 可有多个,提交后按 Spring 顺序调用 | | `OrdoEventListener` | 可有多个,提交后按 Spring 顺序调用 |
| `OrdoCatalog` | 空列表(仅 REST 打开时装配) | | `OrdoCatalog` | REST 打开时:从 `NamedCondition` / `NamedAction` 投影;皆空则为空列表。`assignees` 仍空 |
未提供自定义 Bean 时,ACTION 步骤仍会推进流程,但 handler 什么都不做。 未提供 `NamedAction` 且未覆盖 `ActionHandler` 时,ACTION 步骤仍会推进流程,但 handler 什么都不做。不要同时提供门面 Bean 与对应 `Named*`(门面优先,具名 Bean 不参与运行时)。
内存引擎把 `DispatchingRoutingCondition.of(...)` / `DispatchingActionHandler.of(...)` 传入 `InMemoryOrdoEngine` 即可。
### 2.3 可选 REST ### 2.3 可选 REST
@@ -294,9 +298,9 @@ v1:至少 2 条分支;禁止套娃 PARALLEL;join 固定 ALL;任一分支
无条件边是默认分支;`priority` 只在同类边之间比较(多条条件边之间,或多条无条件边之间)。 无条件边是默认分支;`priority` 只在同类边之间比较(多条条件边之间,或多条无条件边之间)。
`RoutingCondition.matches` 看到 `args` 与 `ProcessRuntime`(含业务 `context`、发起人、定义与当前步)。看不到任务意见。上下文在 `start` 时写入,运行中引擎不会改 context。未知 `ref` 由宿主返回 `false`,该边不匹配。内置谓词仍只读 `ProcessContext` 变量。 `RoutingCondition.matches` 看到 `args` 与 `ProcessRuntime`(含业务 `context`、发起人、定义与当前步)。看不到任务意见。上下文在 `start` 时写入,运行中引擎不会改 context。内置谓词仍只读 `ProcessContext` 变量。
引擎只注入**一个** `RoutingCondition`。Spring 下多个该类型 Bean 会冲突。宿主用一个门面按 `ref` 分发;不要指望引擎按定义拆 bean。 引擎仍只注入**一个** `RoutingCondition`。Spring 下注册多个 `NamedCondition` Bean(`key()` 对应 `when.ref`);无门面且列表非空时装配官方分发器。未知 `ref` 为 false,该边不匹配。重复 `key` 启动失败。也可继续提供单个 `RoutingCondition` 门面自行分发(不要与 `NamedCondition` 混用)。无 `NamedCondition` 时默认仍是恒 true。
## 7. ACTION 步骤 ## 7. ACTION 步骤
@@ -307,22 +311,25 @@ v1:至少 2 条分支;禁止套娃 PARALLEL;join 固定 ALL;任一分支
3. 事务提交后调用 `ActionHandler.execute(actionKey, runtime)`。 3. 事务提交后调用 `ActionHandler.execute(actionKey, runtime)`。
4. 成功 → `SUCCESS` + 事件 `ACTION_SUCCEEDED`;失败 → `FAILED`(`errorMessage`)+ `ACTION_FAILED` + 日志 WARNING。 4. 成功 → `SUCCESS` + 事件 `ACTION_SUCCEEDED`;失败 → `FAILED`(`errorMessage`)+ `ACTION_FAILED` + 日志 WARNING。
**失败不回滚已提交的审批,不阻塞后续步骤,引擎不做重试。** 宿主用 `queryActionExecutions` 或 listener 自行补发。 **失败不回滚已提交的审批,不阻塞后续步骤,引擎不做重试。** 宿主用 `queryActionExecutions` 或 listener 自行补发。分发器遇到未知 `actionKey` 会抛 `IllegalArgumentException`,记为该次 ACTION `FAILED`。
```java ```java
@Component @Component
public class MailActions implements ActionHandler { public class LeaveApprovedMail implements NamedAction {
@Override @Override
public void execute(String actionKey, ProcessRuntime runtime) { public String key() {
switch (actionKey) { return "leave-approved-mail";
case "leave-submitted-mail" -> { /* ... */ }
case "leave-approved-mail" -> { /* ... */ }
default -> throw new IllegalStateException("unknown action: " + actionKey);
} }
@Override
public void execute(ProcessRuntime runtime) {
/* ... */
} }
} }
``` ```
仍可提供单个 `ActionHandler` 按 key 自行分发;不要与 `NamedAction` 混用。
## 8. 审计与监听 ## 8. 审计与监听
`queryHistory(instanceId, page)`:该实例事件,**发生时间升序**。 `queryHistory(instanceId, page)`:该实例事件,**发生时间升序**。
@@ -1,9 +1,15 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api;
import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.runtime.ProcessInstance;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@@ -1,4 +1,6 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import com.jetlumen.ordo.api.runtime.TaskStatus;
/** /**
* Decision rule applied when an approval step has more than one candidate. * Decision rule applied when an approval step has more than one candidate.
@@ -1,9 +1,11 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.util.Texts;
/** /**
* A named step in a process definition. Approval steps have one or more candidate assignees; * A named step in a process definition. Approval steps have one or more candidate assignees;
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
/** What happens when an approval step's due time is reached. */ /** What happens when an approval step's due time is reached. */
public enum DueThen { public enum DueThen {
@@ -1,8 +1,9 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.jetlumen.ordo.api.util.Texts;
/** One branch inside a {@link StepKind#PARALLEL} block. The first step id is the branch start. */ /** One branch inside a {@link StepKind#PARALLEL} block. The first step id is the branch start. */
public record ParallelBranch(String id, List<String> stepIds) { public record ParallelBranch(String id, List<String> stepIds) {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
/** Locates an inner step inside a {@link StepKind#PARALLEL} block. */ /** Locates an inner step inside a {@link StepKind#PARALLEL} block. */
public record ParallelMembership(ApprovalStep parallel, ParallelBranch branch) { public record ParallelMembership(ApprovalStep parallel, ParallelBranch branch) {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
@@ -9,6 +9,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import com.jetlumen.ordo.api.util.Texts;
/** Immutable blueprint for an approval process with explicit step transitions. */ /** Immutable blueprint for an approval process with explicit step transitions. */
public record ProcessDefinition(String id, int version, String name, List<ApprovalStep> steps, public record ProcessDefinition(String id, int version, String name, List<ApprovalStep> steps,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import com.jetlumen.ordo.api.util.Jsons;
/** Parses a structural JSON process graph into a {@link ProcessDefinition}. */ /** Parses a structural JSON process graph into a {@link ProcessDefinition}. */
public final class ProcessDefinitionParser { public final class ProcessDefinitionParser {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -11,6 +11,8 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.util.Texts;
/** Closed-set boolean tree evaluated against {@link ProcessContext} variables. */ /** Closed-set boolean tree evaluated against {@link ProcessContext} variables. */
public sealed interface RoutingPredicate permits RoutingPredicate.Compare, RoutingPredicate.In, public sealed interface RoutingPredicate permits RoutingPredicate.Compare, RoutingPredicate.In,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
@@ -9,6 +9,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.util.Jsons;
import com.jetlumen.ordo.api.util.Texts;
/** /**
* Outgoing-edge condition: either a built-in {@link RoutingPredicate} or a host * Outgoing-edge condition: either a built-in {@link RoutingPredicate} or a host
@@ -1,7 +1,8 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import java.time.Duration; import java.time.Duration;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.util.Texts;
/** Relative SLA on an approval step. */ /** Relative SLA on an approval step. */
public record StepDue(Duration after, DueThen then, String to, String action) { public record StepDue(Duration after, DueThen then, String to, String action) {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
public enum StepKind { public enum StepKind {
APPROVAL, ACTION, PARALLEL APPROVAL, ACTION, PARALLEL
@@ -1,4 +1,6 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.definition;
import com.jetlumen.ordo.api.util.Texts;
/** /**
* An outgoing edge from an approval step. When {@link #toStepId()} is {@code null}, matching this * An outgoing edge from an approval step. When {@link #toStepId()} is {@code null}, matching this
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.query; package com.jetlumen.ordo.api.query;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import java.time.Instant; import java.time.Instant;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.query; package com.jetlumen.ordo.api.query;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import java.time.Instant; import java.time.Instant;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.InstanceToken; import com.jetlumen.ordo.api.runtime.InstanceToken;
import java.util.List; import java.util.List;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.repository; package com.jetlumen.ordo.api.repository;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,7 +1,8 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.util.Texts;
/** Persisted record of an ACTION step invocation. */ /** Persisted record of an ACTION step invocation. */
public record ActionExecution(String id, String instanceId, String stepId, String actionKey, public record ActionExecution(String id, String instanceId, String stepId, String actionKey,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
/** Lifecycle of a persisted ACTION-step execution. */ /** Lifecycle of a persisted ACTION-step execution. */
public enum ActionExecutionStatus { public enum ActionExecutionStatus {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.time.Instant; import java.time.Instant;
@@ -1,6 +1,8 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.util.Texts;
/** Runtime token for one branch of a {@link StepKind#PARALLEL} block. */ /** Runtime token for one branch of a {@link StepKind#PARALLEL} block. */
public record InstanceToken(String id, String instanceId, String parallelStepId, String branchId, String currentStepId, public record InstanceToken(String id, String instanceId, String parallelStepId, String branchId, String currentStepId,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@@ -1,7 +1,8 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.util.Texts;
/** Immutable audit record of something that happened to a process instance. */ /** Immutable audit record of something that happened to a process instance. */
public record ProcessEvent(String id, String instanceId, String taskId, String stepId, ProcessEventType type, public record ProcessEvent(String id, String instanceId, String taskId, String stepId, ProcessEventType type,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
/** Kinds of append-only process history events. */ /** Kinds of append-only process history events. */
public enum ProcessEventType { public enum ProcessEventType {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.time.Instant; import java.time.Instant;
@@ -1,6 +1,7 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.util.Texts;
/** /**
* Read-only engine metadata plus business {@link ProcessContext} for host SPIs. * Read-only engine metadata plus business {@link ProcessContext} for host SPIs.
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
public enum ProcessStatus { public enum ProcessStatus {
RUNNING, APPROVED, REJECTED, WITHDRAWN, CANCELLED RUNNING, APPROVED, REJECTED, WITHDRAWN, CANCELLED
@@ -1,7 +1,8 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; import java.util.Objects;
import com.jetlumen.ordo.api.util.Texts;
/** Immutable audit record created when an approval task is completed. */ /** Immutable audit record created when an approval task is completed. */
public record TaskAction(String actor, String comment, Instant operatedAt) { public record TaskAction(String actor, String comment, Instant operatedAt) {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
public enum TaskStatus { public enum TaskStatus {
PENDING, APPROVED, REJECTED, PENDING, APPROVED, REJECTED,
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.runtime;
/** Status of a parallel-branch token. */ /** Status of a parallel-branch token. */
public enum TokenStatus { public enum TokenStatus {
@@ -1,9 +1,12 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.spi;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
/** /**
* Executes a named action step against the running instance. Hosts supply a * Executes a named action step against the running instance. Hosts supply a
* singleton implementation (same pattern as {@link RoutingCondition}); the database only stores * singleton implementation (same pattern as {@link RoutingCondition}); the database only stores
* the {@code actionKey} string. * the {@code actionKey} string. Prefer {@link NamedAction} beans; Spring wires a dispatcher
* when this facade is not defined.
*/ */
@FunctionalInterface @FunctionalInterface
public interface ActionHandler { public interface ActionHandler {
@@ -1,4 +1,7 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.spi;
import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
/** /**
* Resolves the actual assignee for a single candidate of an approval step when its task is * Resolves the actual assignee for a single candidate of an approval step when its task is
@@ -0,0 +1,27 @@
package com.jetlumen.ordo.api.spi;
import java.util.List;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
/**
* A single ACTION implementation keyed by {@link #key()}, matching {@code action} on the step
* (and {@code due.then.notify} keys). Spring collects these beans into a dispatching
* {@link ActionHandler} when the host does not define that facade itself.
*/
public interface NamedAction {
String key();
void execute(ProcessRuntime runtime);
default String label() {
return key();
}
default List<OrdoCatalog.Param> params() {
return List.of();
}
default OrdoCatalog.Item catalogItem() {
return new OrdoCatalog.Item(key(), label(), params());
}
}
@@ -0,0 +1,28 @@
package com.jetlumen.ordo.api.spi;
import java.util.List;
import java.util.Map;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
/**
* A single routing condition keyed by {@link #key()}, matching {@code when.ref}. Spring collects
* these beans into a dispatching {@link RoutingCondition} when the host does not define that
* facade itself.
*/
public interface NamedCondition {
String key();
boolean matches(Map<String, Object> args, ProcessRuntime runtime);
default String label() {
return key();
}
default List<OrdoCatalog.Param> params() {
return List.of();
}
default OrdoCatalog.Item catalogItem() {
return new OrdoCatalog.Item(key(), label(), params());
}
}
@@ -1,9 +1,10 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.spi;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import com.jetlumen.ordo.api.util.Texts;
/** Host-registered keys for designers and REST dropdowns; not used by the engine at runtime. */ /** Host-registered keys for designers and REST dropdowns; not used by the engine at runtime. */
public interface OrdoCatalog { public interface OrdoCatalog {
@@ -1,4 +1,6 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.spi;
import com.jetlumen.ordo.api.runtime.ProcessEvent;
/** /**
* Host hook invoked after a process mutation has been committed. Implementations must not throw * Host hook invoked after a process mutation has been committed. Implementations must not throw
@@ -1,11 +1,13 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.spi;
import java.util.Map; import java.util.Map;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
/** /**
* Evaluates a named routing condition ({@code when.ref}) against the running instance. * Evaluates a named routing condition ({@code when.ref}) against the running instance.
* Hosts supply a singleton implementation (same pattern as {@link AssigneeResolver}); the * Hosts supply a singleton implementation (same pattern as {@link AssigneeResolver}); the
* definition stores the {@code ref} key and optional {@code args}. * definition stores the {@code ref} key and optional {@code args}. Prefer {@link NamedCondition}
* beans; Spring wires a dispatcher when this facade is not defined.
*/ */
@FunctionalInterface @FunctionalInterface
public interface RoutingCondition { public interface RoutingCondition {
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.util;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.api; package com.jetlumen.ordo.api.util;
/** Shared blank-string checks used by domain records and the engine. */ /** Shared blank-string checks used by domain records and the engine. */
public final class Texts { public final class Texts {
@@ -8,6 +8,13 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.definition.ProcessDefinitionParser;
import com.jetlumen.ordo.api.definition.RoutingPredicate;
import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.definition.StepTransition;
class ProcessDefinitionParserTest { class ProcessDefinitionParserTest {
@@ -7,6 +7,14 @@ import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.definition.RoutingWhen;
import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.definition.StepTransition;
class ProcessDefinitionTest { class ProcessDefinitionTest {
@@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.jetlumen.ordo.api.definition.RoutingWhen;
class RoutingWhenTest { class RoutingWhenTest {
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.api.query; package com.jetlumen.ordo.api.query;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.time.Instant; import java.time.Instant;
@@ -1,28 +1,28 @@
package com.jetlumen.ordo.core; package com.jetlumen.ordo.core;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalPolicy; import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.OrdoEventListener; import com.jetlumen.ordo.api.spi.OrdoEventListener;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessRuntime; import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import com.jetlumen.ordo.api.ProcessEventType; import com.jetlumen.ordo.api.runtime.ProcessEventType;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.RoutingWhen; import com.jetlumen.ordo.api.definition.RoutingWhen;
import com.jetlumen.ordo.api.StepDue; import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.TaskAction; import com.jetlumen.ordo.api.runtime.TaskAction;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.TransactionExecutor; import com.jetlumen.ordo.api.TransactionExecutor;
import com.jetlumen.ordo.api.exception.DefinitionNotFoundException; import com.jetlumen.ordo.api.exception.DefinitionNotFoundException;
import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException; import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException;
@@ -36,10 +36,10 @@ import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
import com.jetlumen.ordo.api.InstanceToken; import com.jetlumen.ordo.api.runtime.InstanceToken;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ParallelMembership; import com.jetlumen.ordo.api.definition.ParallelMembership;
import com.jetlumen.ordo.api.TokenStatus; import com.jetlumen.ordo.api.runtime.TokenStatus;
import com.jetlumen.ordo.api.repository.ActionExecutionRepository; import com.jetlumen.ordo.api.repository.ActionExecutionRepository;
import com.jetlumen.ordo.api.repository.ApprovalTaskRepository; import com.jetlumen.ordo.api.repository.ApprovalTaskRepository;
import com.jetlumen.ordo.api.repository.InstanceTokenRepository; import com.jetlumen.ordo.api.repository.InstanceTokenRepository;
@@ -59,7 +59,9 @@ import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import static com.jetlumen.ordo.api.Texts.requireText; import static com.jetlumen.ordo.api.util.Texts.requireText;
import com.jetlumen.ordo.core.routing.RoutingPredicateEvaluator;
/** /**
* Repository-backed implementation of the approval runtime with explicit step transitions. * Repository-backed implementation of the approval runtime with explicit step transitions.
@@ -1,16 +1,16 @@
package com.jetlumen.ordo.core; package com.jetlumen.ordo.core;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.OrdoEventListener; import com.jetlumen.ordo.api.spi.OrdoEventListener;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ActionExecutionRepository; import com.jetlumen.ordo.api.repository.ActionExecutionRepository;
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.InstanceToken; import com.jetlumen.ordo.api.runtime.InstanceToken;
import com.jetlumen.ordo.api.TokenStatus; import com.jetlumen.ordo.api.runtime.TokenStatus;
import com.jetlumen.ordo.api.repository.InstanceTokenRepository; import com.jetlumen.ordo.api.repository.InstanceTokenRepository;
import java.util.ArrayList; import java.util.ArrayList;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository; import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ProcessHistoryRepository; import com.jetlumen.ordo.api.repository.ProcessHistoryRepository;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,13 +1,13 @@
package com.jetlumen.ordo.core; package com.jetlumen.ordo.core.routing;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.RoutingPredicate; import com.jetlumen.ordo.api.definition.RoutingPredicate;
import com.jetlumen.ordo.api.RoutingPredicate.And; import com.jetlumen.ordo.api.definition.RoutingPredicate.And;
import com.jetlumen.ordo.api.RoutingPredicate.Compare; import com.jetlumen.ordo.api.definition.RoutingPredicate.Compare;
import com.jetlumen.ordo.api.RoutingPredicate.In; import com.jetlumen.ordo.api.definition.RoutingPredicate.In;
import com.jetlumen.ordo.api.RoutingPredicate.Not; import com.jetlumen.ordo.api.definition.RoutingPredicate.Not;
import com.jetlumen.ordo.api.RoutingPredicate.Op; import com.jetlumen.ordo.api.definition.RoutingPredicate.Op;
import com.jetlumen.ordo.api.RoutingPredicate.Or; import com.jetlumen.ordo.api.definition.RoutingPredicate.Or;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@@ -0,0 +1,30 @@
package com.jetlumen.ordo.core.spi;
import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import java.util.List;
import java.util.Map;
/** {@link ActionHandler} that dispatches by {@link NamedAction#key()}. */
public final class DispatchingActionHandler implements ActionHandler {
private final Map<String, NamedAction> actions;
private DispatchingActionHandler(Map<String, NamedAction> actions) {
this.actions = actions;
}
public static DispatchingActionHandler of(List<? extends NamedAction> actions) {
return new DispatchingActionHandler(NamedHandlers.indexByKey(actions, NamedAction::key, "action"));
}
@Override
public void execute(String actionKey, ProcessRuntime runtime) {
NamedAction action = actions.get(NamedHandlers.lookupKey(actionKey));
if (action == null) {
throw new IllegalArgumentException("unknown action: " + actionKey);
}
action.execute(runtime);
}
}
@@ -0,0 +1,30 @@
package com.jetlumen.ordo.core.spi;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import com.jetlumen.ordo.api.spi.RoutingCondition;
import java.util.List;
import java.util.Map;
/** {@link RoutingCondition} that dispatches by {@link NamedCondition#key()}. Unknown keys are false. */
public final class DispatchingRoutingCondition implements RoutingCondition {
private final Map<String, NamedCondition> conditions;
private DispatchingRoutingCondition(Map<String, NamedCondition> conditions) {
this.conditions = conditions;
}
public static DispatchingRoutingCondition of(List<? extends NamedCondition> conditions) {
return new DispatchingRoutingCondition(NamedHandlers.indexByKey(conditions, NamedCondition::key, "condition"));
}
@Override
public boolean matches(String conditionKey, Map<String, Object> args, ProcessRuntime runtime) {
NamedCondition condition = conditions.get(NamedHandlers.lookupKey(conditionKey));
if (condition == null) {
return false;
}
return condition.matches(args, runtime);
}
}
@@ -0,0 +1,36 @@
package com.jetlumen.ordo.core.spi;
import com.jetlumen.ordo.api.util.Texts;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
final class NamedHandlers {
private NamedHandlers() {
}
static String requireKey(String key) {
Texts.requireText(key, "key");
return key.strip();
}
static String lookupKey(String key) {
return key == null ? "" : key.strip();
}
static <T> Map<String, T> indexByKey(List<? extends T> items, Function<T, String> keyExtractor, String kind) {
Objects.requireNonNull(items, kind + "s must not be null");
Map<String, T> map = new LinkedHashMap<>();
for (T item : items) {
Objects.requireNonNull(item, kind + " must not be null");
String key = requireKey(keyExtractor.apply(item));
if (map.put(key, item) != null) {
throw new IllegalStateException("duplicate " + kind + " key: " + key);
}
}
return Map.copyOf(map);
}
}
@@ -0,0 +1,38 @@
package com.jetlumen.ordo.core.spi;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.spi.OrdoCatalog;
import java.util.List;
import java.util.Objects;
/** Catalog projected from registered {@link NamedCondition} and {@link NamedAction} instances. */
public final class RegistryOrdoCatalog implements OrdoCatalog {
private final List<Item> conditions;
private final List<Item> actions;
public RegistryOrdoCatalog(List<? extends NamedCondition> conditions, List<? extends NamedAction> actions) {
this.conditions = Objects.requireNonNull(conditions, "conditions must not be null").stream()
.map(NamedCondition::catalogItem)
.toList();
this.actions = Objects.requireNonNull(actions, "actions must not be null").stream()
.map(NamedAction::catalogItem)
.toList();
}
@Override
public List<Item> conditions() {
return conditions;
}
@Override
public List<Item> actions() {
return actions;
}
@Override
public List<Item> assignees() {
return List.of();
}
}
@@ -1,25 +1,25 @@
package com.jetlumen.ordo.core; package com.jetlumen.ordo.core;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.ApprovalPolicy; import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessEventType; import com.jetlumen.ordo.api.runtime.ProcessEventType;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessRuntime; import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.RoutingPredicate; import com.jetlumen.ordo.api.definition.RoutingPredicate;
import com.jetlumen.ordo.api.StepDue; import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.exception.DefinitionNotFoundException; import com.jetlumen.ordo.api.exception.DefinitionNotFoundException;
import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException; import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException;
import com.jetlumen.ordo.api.exception.InstanceNotFoundException; import com.jetlumen.ordo.api.exception.InstanceNotFoundException;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.core; package com.jetlumen.ordo.core;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.RoutingPredicate; import com.jetlumen.ordo.api.definition.RoutingPredicate;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List; import java.util.List;
@@ -9,6 +9,7 @@ import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.jetlumen.ordo.core.routing.RoutingPredicateEvaluator;
class RoutingPredicateEvaluatorTest { class RoutingPredicateEvaluatorTest {
@@ -1,10 +1,10 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.core.repository; package com.jetlumen.ordo.core.repository;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -0,0 +1,134 @@
package com.jetlumen.ordo.core.spi;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
class DispatchingHandlersTest {
private static final ProcessRuntime RUNTIME =
new ProcessRuntime("inst", "def", 1, "alice", "step", ProcessContext.empty());
@Test
void actionDispatchesByKey() {
List<String> executed = new ArrayList<>();
DispatchingActionHandler.of(List.of(action("mail", executed::add)))
.execute("mail", RUNTIME);
assertEquals(List.of("mail"), executed);
}
@Test
void actionStripsKeyOnRegisterAndLookup() {
List<String> executed = new ArrayList<>();
DispatchingActionHandler.of(List.of(action(" mail ", executed::add)))
.execute("mail", RUNTIME);
assertEquals(List.of(" mail "), executed);
}
@Test
void unknownActionThrows() {
DispatchingActionHandler handler = DispatchingActionHandler.of(List.of(action("mail", key -> {
})));
IllegalArgumentException error = assertThrows(IllegalArgumentException.class,
() -> handler.execute("other", RUNTIME));
assertEquals("unknown action: other", error.getMessage());
}
@Test
void duplicateActionKeyFailsFast() {
IllegalStateException error = assertThrows(IllegalStateException.class,
() -> DispatchingActionHandler.of(List.of(action("mail", key -> {
}), action("mail", key -> {
}))));
assertEquals("duplicate action key: mail", error.getMessage());
}
@Test
void blankActionKeyRejected() {
assertThrows(IllegalArgumentException.class,
() -> DispatchingActionHandler.of(List.of(action(" ", key -> {
}))));
}
@Test
void conditionDispatchesByKey() {
DispatchingRoutingCondition condition = DispatchingRoutingCondition.of(List.of(
namedCondition("amountGt", (args, runtime) -> ((Number) args.get("threshold")).intValue() < 10)));
assertTrue(condition.matches("amountGt", Map.of("threshold", 5), RUNTIME));
assertFalse(condition.matches("amountGt", Map.of("threshold", 20), RUNTIME));
}
@Test
void unknownConditionIsFalse() {
DispatchingRoutingCondition condition = DispatchingRoutingCondition.of(List.of(
namedCondition("amountGt", (args, runtime) -> true)));
assertFalse(condition.matches("missing", Map.of(), RUNTIME));
}
@Test
void duplicateConditionKeyFailsFast() {
IllegalStateException error = assertThrows(IllegalStateException.class,
() -> DispatchingRoutingCondition.of(List.of(
namedCondition("amountGt", (args, runtime) -> true),
namedCondition("amountGt", (args, runtime) -> false))));
assertEquals("duplicate condition key: amountGt", error.getMessage());
}
@Test
void blankConditionKeyRejected() {
assertThrows(IllegalArgumentException.class,
() -> DispatchingRoutingCondition.of(List.of(namedCondition("", (args, runtime) -> true))));
}
@Test
void catalogProjectsNamedHandlers() {
RegistryOrdoCatalog catalog = new RegistryOrdoCatalog(
List.of(namedCondition("amountGt", (args, runtime) -> true)),
List.of(action("mail", key -> {
})));
assertEquals("amountGt", catalog.conditions().get(0).key());
assertEquals("mail", catalog.actions().get(0).key());
assertTrue(catalog.assignees().isEmpty());
}
private static NamedAction action(String key, Consumer<String> onExecute) {
return new NamedAction() {
@Override
public String key() {
return key;
}
@Override
public void execute(ProcessRuntime runtime) {
onExecute.accept(key);
}
};
}
private static NamedCondition namedCondition(String key, BiFunction<Map<String, Object>, ProcessRuntime, Boolean> delegate) {
return new NamedCondition() {
@Override
public String key() {
return key;
}
@Override
public boolean matches(Map<String, Object> args, ProcessRuntime runtime) {
return delegate.apply(args, runtime);
}
};
}
}
@@ -1,9 +1,9 @@
package com.jetlumen.ordo.example; package com.jetlumen.ordo.example;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.core.InMemoryOrdoEngine; import com.jetlumen.ordo.core.InMemoryOrdoEngine;
import java.util.List; import java.util.List;
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.spring.jdbc; package com.jetlumen.ordo.spring;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessDefinitionParser; import com.jetlumen.ordo.api.definition.ProcessDefinitionParser;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
@@ -1,4 +1,4 @@
package com.jetlumen.ordo.spring.jdbc; package com.jetlumen.ordo.spring;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
@@ -1,10 +1,12 @@
package com.jetlumen.ordo.spring.jdbc; package com.jetlumen.ordo.spring.jdbc;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.OrdoEventListener; import com.jetlumen.ordo.api.spi.OrdoEventListener;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.TransactionExecutor; import com.jetlumen.ordo.api.TransactionExecutor;
import com.jetlumen.ordo.api.repository.ActionExecutionRepository; import com.jetlumen.ordo.api.repository.ActionExecutionRepository;
import com.jetlumen.ordo.api.repository.ApprovalTaskRepository; import com.jetlumen.ordo.api.repository.ApprovalTaskRepository;
@@ -13,6 +15,10 @@ import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository;
import com.jetlumen.ordo.api.repository.ProcessHistoryRepository; import com.jetlumen.ordo.api.repository.ProcessHistoryRepository;
import com.jetlumen.ordo.api.repository.ProcessInstanceRepository; import com.jetlumen.ordo.api.repository.ProcessInstanceRepository;
import com.jetlumen.ordo.core.DefaultOrdoEngine; import com.jetlumen.ordo.core.DefaultOrdoEngine;
import com.jetlumen.ordo.core.spi.DispatchingActionHandler;
import com.jetlumen.ordo.core.spi.DispatchingRoutingCondition;
import com.jetlumen.ordo.spring.OrdoDefinitionLoader;
import com.jetlumen.ordo.spring.OrdoDuePoller;
import com.jetlumen.ordo.spring.OrdoProperties; import com.jetlumen.ordo.spring.OrdoProperties;
import com.jetlumen.ordo.storage.jdbc.JdbcActionExecutionRepository; import com.jetlumen.ordo.storage.jdbc.JdbcActionExecutionRepository;
import com.jetlumen.ordo.storage.jdbc.JdbcApprovalTaskRepository; import com.jetlumen.ordo.storage.jdbc.JdbcApprovalTaskRepository;
@@ -37,6 +43,7 @@ import org.springframework.context.annotation.Bean;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.time.Clock; import java.time.Clock;
import java.util.List;
/** /**
* Autoconfigures a JDBC-backed {@link OrdoEngine} when a {@link DataSource} bean is * Autoconfigures a JDBC-backed {@link OrdoEngine} when a {@link DataSource} bean is
@@ -72,14 +79,16 @@ public class OrdoJdbcAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public RoutingCondition ordoRoutingCondition() { public RoutingCondition ordoRoutingCondition(ObjectProvider<NamedCondition> namedConditions) {
return RoutingCondition.always(); List<NamedCondition> conditions = namedConditions.orderedStream().toList();
return conditions.isEmpty() ? RoutingCondition.always() : DispatchingRoutingCondition.of(conditions);
} }
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ActionHandler ordoActionHandler() { public ActionHandler ordoActionHandler(ObjectProvider<NamedAction> namedActions) {
return ActionHandler.noop(); List<NamedAction> actions = namedActions.orderedStream().toList();
return actions.isEmpty() ? ActionHandler.noop() : DispatchingActionHandler.of(actions);
} }
@Bean @Bean
@@ -2,9 +2,9 @@ package com.jetlumen.ordo.spring.rest;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jetlumen.ordo.api.Jsons; import com.jetlumen.ordo.api.util.Jsons;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessDefinitionParser; import com.jetlumen.ordo.api.definition.ProcessDefinitionParser;
import java.util.Map; import java.util.Map;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.OrdoCatalog; import com.jetlumen.ordo.api.spi.OrdoCatalog;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessDefinitionParser; import com.jetlumen.ordo.api.definition.ProcessDefinitionParser;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -1,12 +1,12 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -1,9 +1,13 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.OrdoCatalog; import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.spi.OrdoCatalog;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.core.spi.RegistryOrdoCatalog;
import com.jetlumen.ordo.spring.OrdoProperties; import com.jetlumen.ordo.spring.OrdoProperties;
import com.jetlumen.ordo.spring.jdbc.OrdoJdbcAutoConfiguration; import com.jetlumen.ordo.spring.jdbc.OrdoJdbcAutoConfiguration;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -15,6 +19,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
import java.util.List;
@AutoConfiguration @AutoConfiguration
@ConditionalOnClass(DispatcherServlet.class) @ConditionalOnClass(DispatcherServlet.class)
@ConditionalOnProperty(prefix = "ordo.rest", name = "enabled", havingValue = "true") @ConditionalOnProperty(prefix = "ordo.rest", name = "enabled", havingValue = "true")
@@ -33,7 +39,13 @@ public class OrdoRestAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public OrdoCatalog ordoCatalog() { public OrdoCatalog ordoCatalog(ObjectProvider<NamedAction> namedActions,
ObjectProvider<NamedCondition> namedConditions) {
List<NamedAction> actions = namedActions.orderedStream().toList();
List<NamedCondition> conditions = namedConditions.orderedStream().toList();
if (actions.isEmpty() && conditions.isEmpty()) {
return OrdoCatalog.empty(); return OrdoCatalog.empty();
} }
return new RegistryOrdoCatalog(conditions, actions);
}
} }
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -1,18 +1,24 @@
package com.jetlumen.ordo.spring.jdbc; package com.jetlumen.ordo.spring.jdbc;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.OrdoEventListener; import com.jetlumen.ordo.api.spi.OrdoEventListener;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessEventType; import com.jetlumen.ordo.api.runtime.ProcessEventType;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository; import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository;
import com.jetlumen.ordo.core.spi.DispatchingActionHandler;
import com.jetlumen.ordo.core.spi.DispatchingRoutingCondition;
import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect; import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
@@ -23,10 +29,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.jetlumen.ordo.spring.OrdoDefinitionLoader;
class OrdoJdbcAutoConfigurationTest { class OrdoJdbcAutoConfigurationTest {
@@ -168,6 +176,54 @@ class OrdoJdbcAutoConfigurationTest {
}); });
} }
@Test
void keepsNoopAndAlwaysWhenNoNamedHandlers() {
withDataSourceRunner.run(context -> {
context.getBean(ActionHandler.class).execute("any", null);
assertThat(context.getBean(RoutingCondition.class).matches("any", Map.of(), null)).isTrue();
});
}
@Test
void assemblesDispatchingActionHandlerFromNamedActions() {
withDataSourceRunner.withUserConfiguration(NamedActionConfig.class)
.run(context -> {
assertThat(context.getBean(ActionHandler.class)).isInstanceOf(DispatchingActionHandler.class);
OrdoEngine engine = context.getBean(OrdoEngine.class);
engine.publish(new ProcessDefinition("leave", "Leave",
List.of(ApprovalStep.action("notify", "Notify", "leave-mail")),
List.of(StepTransition.end("notify"))));
engine.start("leave", "alice");
assertThat(context.getBean(RecordingNamedAction.class).executed).containsExactly("leave-mail");
});
}
@Test
void honoursUserDefinedActionHandlerOverNamedActions() {
withDataSourceRunner.withUserConfiguration(CustomActionHandlerConfig.class, NamedActionConfig.class)
.run(context -> assertThatThrownBy(() -> context.getBean(ActionHandler.class).execute("any", null))
.isInstanceOf(IllegalStateException.class)
.hasMessage("custom-action"));
}
@Test
void assemblesDispatchingRoutingConditionFromNamedConditions() {
withDataSourceRunner.withUserConfiguration(NamedConditionConfig.class)
.run(context -> {
RoutingCondition routing = context.getBean(RoutingCondition.class);
assertThat(routing).isInstanceOf(DispatchingRoutingCondition.class);
assertThat(routing.matches("amountGt", Map.of(), null)).isTrue();
assertThat(routing.matches("other", Map.of(), null)).isFalse();
});
}
@Test
void honoursUserDefinedRoutingConditionOverNamedConditions() {
withDataSourceRunner.withUserConfiguration(CustomRoutingConditionConfig.class, NamedConditionConfig.class)
.run(context -> assertThat(context.getBean(RoutingCondition.class)
.matches("other", Map.of(), null)).isTrue());
}
@Test @Test
void invokesOrdoEventListenerBeans() { void invokesOrdoEventListenerBeans() {
withDataSourceRunner.withUserConfiguration(RecordingListenerConfig.class) withDataSourceRunner.withUserConfiguration(RecordingListenerConfig.class)
@@ -224,6 +280,46 @@ class OrdoJdbcAutoConfigurationTest {
} }
} }
@Configuration
static class NamedActionConfig {
@Bean
RecordingNamedAction leaveMailAction() {
return new RecordingNamedAction();
}
}
static class RecordingNamedAction implements NamedAction {
final List<String> executed = new java.util.concurrent.CopyOnWriteArrayList<>();
@Override
public String key() {
return "leave-mail";
}
@Override
public void execute(ProcessRuntime runtime) {
executed.add(key());
}
}
@Configuration
static class NamedConditionConfig {
@Bean
NamedCondition amountGt() {
return new NamedCondition() {
@Override
public String key() {
return "amountGt";
}
@Override
public boolean matches(Map<String, Object> args, ProcessRuntime runtime) {
return true;
}
};
}
}
@Configuration @Configuration
static class RecordingListenerConfig { static class RecordingListenerConfig {
@Bean @Bean
@@ -1,6 +1,10 @@
package com.jetlumen.ordo.spring.rest; package com.jetlumen.ordo.spring.rest;
import com.jetlumen.ordo.api.spi.NamedAction;
import com.jetlumen.ordo.api.spi.NamedCondition;
import com.jetlumen.ordo.api.spi.OrdoCatalog;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.runtime.ProcessRuntime;
import com.jetlumen.ordo.spring.jdbc.OrdoFlywayAutoConfiguration; import com.jetlumen.ordo.spring.jdbc.OrdoFlywayAutoConfiguration;
import com.jetlumen.ordo.spring.jdbc.OrdoJdbcAutoConfiguration; import com.jetlumen.ordo.spring.jdbc.OrdoJdbcAutoConfiguration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -12,11 +16,14 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPath;
@@ -76,6 +83,37 @@ class OrdoRestAutoConfigurationTest {
.hasSingleBean(OrdoCatalogController.class)); .hasSingleBean(OrdoCatalogController.class));
} }
@Test
void projectsCatalogFromNamedHandlers() {
runner.withPropertyValues("ordo.rest.enabled=true")
.withUserConfiguration(NamedCatalogConfig.class)
.run(context -> {
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
mvc.perform(get("/ordo/catalog/actions"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].key").value("leave-mail"))
.andExpect(jsonPath("$[0].label").value("Notify HR"));
mvc.perform(get("/ordo/catalog/conditions"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].key").value("amountGt"));
mvc.perform(get("/ordo/catalog/assignees"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isEmpty());
});
}
@Test
void honoursUserDefinedCatalog() {
runner.withPropertyValues("ordo.rest.enabled=true")
.withUserConfiguration(NamedCatalogConfig.class, CustomCatalogConfig.class)
.run(context -> {
MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
mvc.perform(get("/ordo/catalog/actions"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].key").value("custom-action"));
});
}
@Test @Test
void parsePublishStartApproveAndErrorMappings() { void parsePublishStartApproveAndErrorMappings() {
runner.withPropertyValues("ordo.rest.enabled=true").run(context -> { runner.withPropertyValues("ordo.rest.enabled=true").run(context -> {
@@ -149,4 +187,64 @@ class OrdoRestAutoConfigurationTest {
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
}); });
} }
@Configuration
static class NamedCatalogConfig {
@Bean
NamedAction leaveMail() {
return new NamedAction() {
@Override
public String key() {
return "leave-mail";
}
@Override
public String label() {
return "Notify HR";
}
@Override
public void execute(ProcessRuntime runtime) {
}
};
}
@Bean
NamedCondition amountGt() {
return new NamedCondition() {
@Override
public String key() {
return "amountGt";
}
@Override
public boolean matches(Map<String, Object> args, ProcessRuntime runtime) {
return true;
}
};
}
}
@Configuration
static class CustomCatalogConfig {
@Bean
OrdoCatalog ordoCatalog() {
return new OrdoCatalog() {
@Override
public java.util.List<OrdoCatalog.Item> conditions() {
return java.util.List.of();
}
@Override
public java.util.List<OrdoCatalog.Item> actions() {
return java.util.List.of(new OrdoCatalog.Item("custom-action", "Custom"));
}
@Override
public java.util.List<OrdoCatalog.Item> assignees() {
return java.util.List.of();
}
};
}
}
} }
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ActionExecutionRepository; import com.jetlumen.ordo.api.repository.ActionExecutionRepository;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.InstanceToken; import com.jetlumen.ordo.api.runtime.InstanceToken;
import com.jetlumen.ordo.api.TokenStatus; import com.jetlumen.ordo.api.runtime.TokenStatus;
import com.jetlumen.ordo.api.repository.InstanceTokenRepository; import com.jetlumen.ordo.api.repository.InstanceTokenRepository;
import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect; import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect;
import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialects; import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialects;
@@ -1,10 +1,10 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository; import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.repository.ProcessHistoryRepository; import com.jetlumen.ordo.api.repository.ProcessHistoryRepository;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.InstanceQuery; import com.jetlumen.ordo.api.query.InstanceQuery;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -1,18 +1,19 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.ApprovalPolicy; import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.DueThen; import com.jetlumen.ordo.api.definition.DueThen;
import com.jetlumen.ordo.api.StepDue; import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.Duration; import java.time.Duration;
import com.jetlumen.ordo.api.definition.ApprovalStep;
/** /**
* Maps rows of {@code ordo_approval_step}. A step's candidate list lives in the separate * Maps rows of {@code ordo_approval_step}. A step's candidate list lives in the separate
* {@code ordo_step_candidate} table, so this only reads the scalar step columns; the repository * {@code ordo_step_candidate} table, so this only reads the scalar step columns; the repository
* assembles the full {@link com.jetlumen.ordo.api.ApprovalStep} once candidates are loaded. * assembles the full {@link com.jetlumen.ordo.api.definition.ApprovalStep} once candidates are loaded.
*/ */
public final class ApprovalStepMapper { public final class ApprovalStepMapper {
private ApprovalStepMapper() { private ApprovalStepMapper() {
@@ -1,8 +1,8 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.TaskAction; import com.jetlumen.ordo.api.runtime.TaskAction;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -2,8 +2,8 @@ package com.jetlumen.ordo.storage.jdbc.mapper;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jetlumen.ordo.api.Jsons; import com.jetlumen.ordo.api.util.Jsons;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import java.util.Map; import java.util.Map;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessEventType; import com.jetlumen.ordo.api.runtime.ProcessEventType;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -1,7 +1,7 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -1,6 +1,6 @@
package com.jetlumen.ordo.storage.jdbc.mapper; package com.jetlumen.ordo.storage.jdbc.mapper;
import com.jetlumen.ordo.api.RoutingWhen; import com.jetlumen.ordo.api.definition.RoutingWhen;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@@ -1,12 +1,12 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ActionExecution; import com.jetlumen.ordo.api.runtime.ActionExecution;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@@ -1,13 +1,13 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.TaskAction; import com.jetlumen.ordo.api.runtime.TaskAction;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.query.TaskQuery; import com.jetlumen.ordo.api.query.TaskQuery;
@@ -1,19 +1,19 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.TaskAction; import com.jetlumen.ordo.api.runtime.TaskAction;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.core.DefaultOrdoEngine; import com.jetlumen.ordo.core.DefaultOrdoEngine;
import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect; import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialect;
import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialects; import com.jetlumen.ordo.storage.jdbc.dialect.SqlDialects;
@@ -1,25 +1,25 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ActionExecutionStatus; import com.jetlumen.ordo.api.runtime.ActionExecutionStatus;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalPolicy; import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessEvent; import com.jetlumen.ordo.api.runtime.ProcessEvent;
import com.jetlumen.ordo.api.ProcessEventType; import com.jetlumen.ordo.api.runtime.ProcessEventType;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.StepDue; import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException; import com.jetlumen.ordo.api.exception.InstanceAlreadyCompletedException;
import com.jetlumen.ordo.api.exception.UnauthorizedInstanceOperationException; import com.jetlumen.ordo.api.exception.UnauthorizedInstanceOperationException;
import com.jetlumen.ordo.api.exception.NoRouteFoundException; import com.jetlumen.ordo.api.exception.NoRouteFoundException;
@@ -1,19 +1,19 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ActionHandler; import com.jetlumen.ordo.api.spi.ActionHandler;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ApprovalTask; import com.jetlumen.ordo.api.runtime.ApprovalTask;
import com.jetlumen.ordo.api.AssigneeResolver; import com.jetlumen.ordo.api.spi.AssigneeResolver;
import com.jetlumen.ordo.api.OrdoEngine; import com.jetlumen.ordo.api.OrdoEngine;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessContext; import com.jetlumen.ordo.api.runtime.ProcessContext;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.ProcessInstance; import com.jetlumen.ordo.api.runtime.ProcessInstance;
import com.jetlumen.ordo.api.ProcessStatus; import com.jetlumen.ordo.api.runtime.ProcessStatus;
import com.jetlumen.ordo.api.RoutingCondition; import com.jetlumen.ordo.api.spi.RoutingCondition;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.TaskAction; import com.jetlumen.ordo.api.runtime.TaskAction;
import com.jetlumen.ordo.api.TaskStatus; import com.jetlumen.ordo.api.runtime.TaskStatus;
import com.jetlumen.ordo.core.DefaultOrdoEngine; import com.jetlumen.ordo.core.DefaultOrdoEngine;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Assumptions;
@@ -1,13 +1,13 @@
package com.jetlumen.ordo.storage.jdbc; package com.jetlumen.ordo.storage.jdbc;
import com.jetlumen.ordo.api.ApprovalPolicy; import com.jetlumen.ordo.api.definition.ApprovalPolicy;
import com.jetlumen.ordo.api.ApprovalStep; import com.jetlumen.ordo.api.definition.ApprovalStep;
import com.jetlumen.ordo.api.ParallelBranch; import com.jetlumen.ordo.api.definition.ParallelBranch;
import com.jetlumen.ordo.api.ProcessDefinition; import com.jetlumen.ordo.api.definition.ProcessDefinition;
import com.jetlumen.ordo.api.StepDue; import com.jetlumen.ordo.api.definition.StepDue;
import com.jetlumen.ordo.api.StepKind; import com.jetlumen.ordo.api.definition.StepKind;
import com.jetlumen.ordo.api.RoutingPredicate; import com.jetlumen.ordo.api.definition.RoutingPredicate;
import com.jetlumen.ordo.api.StepTransition; import com.jetlumen.ordo.api.definition.StepTransition;
import com.jetlumen.ordo.api.query.Page; import com.jetlumen.ordo.api.query.Page;
import com.jetlumen.ordo.api.query.PageRequest; import com.jetlumen.ordo.api.query.PageRequest;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;

Some files were not shown because too many files have changed in this diff Show More