Skip to content

Commit 697134d

Browse files
Ticket ## : Support repetition rule on milestone
1 parent 13ca68b commit 697134d

21 files changed

Lines changed: 533 additions & 260 deletions

src/CaseManagement.CMMN/Apis/CaseInstancesController.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,29 @@ private static JObject ToDto(CMMNPlanItem planItem)
311311
var result = new JObject
312312
{
313313
{ "id", planItem.Id },
314-
{ "name", planItem.Name }
314+
{ "name", planItem.Name },
315+
{ "version", planItem.Version }
315316
};
317+
var transitionHistories = new JArray();
318+
if (planItem.TransitionHistories != null)
319+
{
320+
foreach(var transitionHistory in planItem.TransitionHistories)
321+
{
322+
transitionHistories.Add(new JObject
323+
{
324+
{ "create_datetime", transitionHistory.CreateDateTime },
325+
{ "transition", Enum.GetName(typeof(CMMNPlanItemTransitions), transitionHistory.Transition).ToLowerInvariant() },
326+
{ "version", transitionHistory.Version }
327+
});
328+
}
329+
}
330+
316331
if (planItem.Status != null)
317332
{
318333
result.Add("status", Enum.GetName(typeof(ProcessFlowInstanceElementStatus), planItem.Status).ToLowerInvariant());
319334
}
320335

336+
result.Add("histories", transitionHistories);
321337
return result;
322338
}
323339

src/CaseManagement.CMMN/CaseInstance/Processors/BaseCMMNTaskProcessor.cs

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,28 @@ namespace CaseManagement.CMMN.CaseInstance.Processors
1313
{
1414
public abstract class BaseCMMNTaskProcessor : IProcessFlowElementProcessor
1515
{
16-
public BaseCMMNTaskProcessor(IDomainEventWatcher domainEventWatcher)
16+
public BaseCMMNTaskProcessor(IDomainEventWatcher domainEventWatcher, IProcessorHelper processorHelper)
1717
{
1818
DomainEventWatcher = domainEventWatcher;
19+
ProcessorHelper = processorHelper;
1920
}
2021

2122
public abstract string ProcessFlowElementType { get; }
2223
protected IDomainEventWatcher DomainEventWatcher { get; private set; }
24+
protected IProcessorHelper ProcessorHelper { get; private set; }
2325

2426
public async Task Handle(WorkflowHandlerContext context, CancellationToken token)
2527
{
26-
bool oneOccurence = false;
28+
RepetitionRuleResultTypes? repetitionRuleResult = RepetitionRuleResultTypes.Repeat;
2729
var pf = context.ProcessFlowInstance;
2830
var cmmnPlanItem = context.GetCMMNPlanItem();
2931
var processTask = ExtractTask(cmmnPlanItem);
3032
int actualVersion = cmmnPlanItem.Version;
3133
if (cmmnPlanItem.Status == null)
3234
{
3335
context.Start(token);
36+
pf.CreatePlanItem(cmmnPlanItem);
37+
/*
3438
DomainEventWatcher.AddCallback(async (obj, e) =>
3539
{
3640
var evt = e.DomainEvent as ProcessFlowInstanceElementStateChangedEvent;
@@ -50,52 +54,15 @@ public async Task Handle(WorkflowHandlerContext context, CancellationToken token
5054
return;
5155
});
5256
await context.StartSubProcess(DomainEventWatcher, token);
57+
*/
5358
}
5459
else
5560
{
56-
if (cmmnPlanItem.RepetitionRule != null && cmmnPlanItem.ActivationRule == CMMNActivationRuleTypes.Repetition)
61+
repetitionRuleResult = ProcessorHelper.HandleRepetitionRule(cmmnPlanItem, pf);
62+
if (repetitionRuleResult != null && repetitionRuleResult == RepetitionRuleResultTypes.Complete)
5763
{
58-
bool isNewInstance = false;
59-
if (cmmnPlanItem.EntryCriterions.Any())
60-
{
61-
oneOccurence = true;
62-
if (cmmnPlanItem.EntryCriterions.Any(s => CheckCriterion(s, pf, actualVersion + 1)))
63-
{
64-
if (cmmnPlanItem.RepetitionRule.Condition != null)
65-
{
66-
if (ExpressionParser.IsValid(cmmnPlanItem.RepetitionRule.Condition.Body, pf))
67-
{
68-
cmmnPlanItem.Create();
69-
isNewInstance = true;
70-
}
71-
}
72-
else
73-
{
74-
cmmnPlanItem.Create();
75-
isNewInstance = true;
76-
}
77-
}
78-
}
79-
else
80-
{
81-
if (cmmnPlanItem.RepetitionRule.Condition != null)
82-
{
83-
if (ExpressionParser.IsValid(cmmnPlanItem.RepetitionRule.Condition.Body, pf))
84-
{
85-
cmmnPlanItem.Create();
86-
isNewInstance = true;
87-
}
88-
}
89-
}
90-
91-
if (!isNewInstance)
92-
{
93-
if (!oneOccurence)
94-
{
95-
Complete(context);
96-
}
97-
return;
98-
}
64+
Complete(context);
65+
return;
9966
}
10067
}
10168

@@ -130,14 +97,14 @@ public async Task Handle(WorkflowHandlerContext context, CancellationToken token
13097
return;
13198
}
13299

133-
await InternalHandle(context, token, oneOccurence);
100+
await InternalHandle(context, token, repetitionRuleResult);
134101
DomainEventWatcher.Quit = true;
135102
});
136103
return;
137104
}
138105
}
139106

140-
await InternalHandle(context, token, oneOccurence);
107+
await InternalHandle(context, token, repetitionRuleResult);
141108
}
142109

143110
public abstract Task Run(WorkflowHandlerContext context, CancellationToken token);
@@ -178,7 +145,7 @@ protected virtual void Complete(WorkflowHandlerContext context)
178145
context.Complete();
179146
}
180147

181-
private async Task InternalHandle(WorkflowHandlerContext context, CancellationToken token, bool oneOccurence)
148+
private async Task InternalHandle(WorkflowHandlerContext context, CancellationToken token, RepetitionRuleResultTypes? repetitionResult)
182149
{
183150
var pf = context.ProcessFlowInstance;
184151
var cmmnPlanItem = context.GetCMMNPlanItem();
@@ -203,7 +170,7 @@ private async Task InternalHandle(WorkflowHandlerContext context, CancellationTo
203170
{
204171
Complete(context);
205172
}
206-
else if (!oneOccurence)
173+
else if (repetitionResult.Value == RepetitionRuleResultTypes.Repeat)
207174
{
208175
await Handle(context, token);
209176
}

src/CaseManagement.CMMN/CaseInstance/Processors/CMMNHumanTaskProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class CMMNHumanTaskProcessor : BaseCMMNTaskProcessor
1515
{
1616
private List<string> _completeElements;
1717

18-
public CMMNHumanTaskProcessor(IDomainEventWatcher domainEventWatcher) : base(domainEventWatcher)
18+
public CMMNHumanTaskProcessor(IDomainEventWatcher domainEventWatcher, IProcessorHelper processorHelper) : base(domainEventWatcher, processorHelper)
1919
{
2020
_completeElements = new List<string>();
2121
}

src/CaseManagement.CMMN/CaseInstance/Processors/CMMNMilestoneProcessor.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,35 @@ namespace CaseManagement.CMMN.CaseInstance.Processors
1111
{
1212
public class CMMNMilestoneProcessor : IProcessFlowElementProcessor
1313
{
14+
private readonly IProcessorHelper _processorHelper;
15+
16+
public CMMNMilestoneProcessor(IProcessorHelper processorHelper)
17+
{
18+
_processorHelper = processorHelper;
19+
}
20+
1421
public string ProcessFlowElementType => Enum.GetName(typeof(CMMNPlanItemDefinitionTypes), CMMNPlanItemDefinitionTypes.Milestone).ToLowerInvariant();
1522

1623
public async Task Handle(WorkflowHandlerContext context, CancellationToken token)
1724
{
18-
context.Start(token);
1925
var pf = context.ProcessFlowInstance;
2026
var cmmnPlanItem = context.GetCMMNPlanItem();
2127
var milestone = cmmnPlanItem.PlanItemMilestone;
28+
if (cmmnPlanItem.Status == null)
29+
{
30+
context.Start(token);
31+
pf.CreatePlanItem(cmmnPlanItem);
32+
}
33+
else
34+
{
35+
var result = _processorHelper.HandleRepetitionRule(cmmnPlanItem, pf);
36+
if (result != null && result == RepetitionRuleResultTypes.Complete)
37+
{
38+
context.Complete();
39+
return;
40+
}
41+
}
42+
2243
if (milestone.State == CMMNMilestoneStates.Available)
2344
{
2445
if (cmmnPlanItem.EntryCriterions.Any() && cmmnPlanItem.EntryCriterions.All(s => !BaseCMMNTaskProcessor.CheckCriterion(s, pf, cmmnPlanItem.Version)))

src/CaseManagement.CMMN/CaseInstance/Processors/CMMNProcessTaskProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class CMMNProcessTaskProcessor : BaseCMMNTaskProcessor
1818
{
1919
private ICaseLaunchProcessCommandHandler _caseLaunchProcessCommandHandler;
2020

21-
public CMMNProcessTaskProcessor(ICaseLaunchProcessCommandHandler caseLaunchProcessCommandHandler, IDomainEventWatcher domainEventHandler) : base(domainEventHandler)
21+
public CMMNProcessTaskProcessor(ICaseLaunchProcessCommandHandler caseLaunchProcessCommandHandler, IDomainEventWatcher domainEventHandler, IProcessorHelper processorHelper) : base(domainEventHandler, processorHelper)
2222
{
2323
_caseLaunchProcessCommandHandler = caseLaunchProcessCommandHandler;
2424
}

src/CaseManagement.CMMN/CaseInstance/Processors/CMMNTaskProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace CaseManagement.CMMN.CaseInstance.Processors
1111
{
1212
public class CMMNTaskProcessor : BaseCMMNTaskProcessor
1313
{
14-
public CMMNTaskProcessor(IDomainEventWatcher domainEventWatcher) : base(domainEventWatcher)
14+
public CMMNTaskProcessor(IDomainEventWatcher domainEventWatcher, IProcessorHelper processorHelper) : base(domainEventWatcher, processorHelper)
1515
{
1616
}
1717

src/CaseManagement.CMMN/CaseInstance/Processors/CMMNTimerEventListenerProcessor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using CaseManagement.Workflow.ISO8601;
77
using CaseManagement.Workflow.Persistence;
88
using System;
9-
using System.Diagnostics;
109
using System.Threading;
1110
using System.Threading.Tasks;
1211

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using CaseManagement.CMMN.Domains;
2+
using CaseManagement.Workflow.Domains;
3+
4+
namespace CaseManagement.CMMN.CaseInstance.Processors
5+
{
6+
public interface IProcessorHelper
7+
{
8+
RepetitionRuleResultTypes? HandleRepetitionRule(CMMNPlanItem cmmnPlanItem, ProcessFlowInstance pf);
9+
}
10+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using CaseManagement.CMMN.Domains;
2+
using CaseManagement.Workflow.Domains;
3+
using CaseManagement.Workflow.Engine;
4+
using System.Linq;
5+
6+
namespace CaseManagement.CMMN.CaseInstance.Processors
7+
{
8+
public class ProcessorHelper : IProcessorHelper
9+
{
10+
public RepetitionRuleResultTypes? HandleRepetitionRule(CMMNPlanItem cmmnPlanItem, ProcessFlowInstance pf)
11+
{
12+
var oneOccurence = false;
13+
int actualVersion = cmmnPlanItem.Version;
14+
if (cmmnPlanItem.RepetitionRule != null && cmmnPlanItem.ActivationRule == CMMNActivationRuleTypes.Repetition)
15+
{
16+
bool isNewInstance = false;
17+
if (cmmnPlanItem.EntryCriterions.Any())
18+
{
19+
oneOccurence = true;
20+
if (cmmnPlanItem.EntryCriterions.Any(s => CheckCriterion(s, pf, actualVersion + 1)))
21+
{
22+
if (cmmnPlanItem.RepetitionRule.Condition != null)
23+
{
24+
if (ExpressionParser.IsValid(cmmnPlanItem.RepetitionRule.Condition.Body, pf))
25+
{
26+
pf.CreatePlanItem(cmmnPlanItem);
27+
// cmmnPlanItem.Create();
28+
isNewInstance = true;
29+
}
30+
}
31+
else
32+
{
33+
pf.CreatePlanItem(cmmnPlanItem);
34+
// cmmnPlanItem.Create();
35+
isNewInstance = true;
36+
}
37+
}
38+
}
39+
else
40+
{
41+
if (cmmnPlanItem.RepetitionRule.Condition != null)
42+
{
43+
if (ExpressionParser.IsValid(cmmnPlanItem.RepetitionRule.Condition.Body, pf))
44+
{
45+
pf.CreatePlanItem(cmmnPlanItem);
46+
isNewInstance = true;
47+
}
48+
}
49+
}
50+
51+
if (!isNewInstance)
52+
{
53+
if (!oneOccurence)
54+
{
55+
return RepetitionRuleResultTypes.Complete;
56+
}
57+
}
58+
}
59+
60+
if (!oneOccurence)
61+
{
62+
return RepetitionRuleResultTypes.Repeat;
63+
}
64+
65+
return null;
66+
}
67+
68+
public static bool CheckCriterion(CMMNCriterion sCriterion, ProcessFlowInstance pf, int currentVersion)
69+
{
70+
foreach (var planItemOnPart in sCriterion.SEntry.PlanItemOnParts)
71+
{
72+
if (!string.IsNullOrWhiteSpace(planItemOnPart.SourceRef))
73+
{
74+
var elt = pf.GetPlanItem(planItemOnPart.SourceRef);
75+
var transitionHistories = elt.TransitionHistories.Where(t => t.Version == currentVersion);
76+
if (elt == null || !transitionHistories.Any() || transitionHistories.Any() && transitionHistories.Last().Transition != planItemOnPart.StandardEvent)
77+
{
78+
return false;
79+
}
80+
}
81+
}
82+
83+
foreach (var fileItemOnPart in sCriterion.SEntry.FileItemOnParts)
84+
{
85+
if (!string.IsNullOrWhiteSpace(fileItemOnPart.SourceRef))
86+
{
87+
var elt = pf.GetCaseFileItem(fileItemOnPart.SourceRef);
88+
if (elt == null || elt.TransitionHistories.Any() && elt.TransitionHistories.Last().Transition != fileItemOnPart.StandardEvent)
89+
{
90+
return false;
91+
}
92+
}
93+
}
94+
95+
return true;
96+
}
97+
}
98+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace CaseManagement.CMMN.CaseInstance.Processors
2+
{
3+
public enum RepetitionRuleResultTypes
4+
{
5+
Complete = 1,
6+
Repeat = 2
7+
}
8+
}

0 commit comments

Comments
 (0)