Skip to content

Commit cac955b

Browse files
committed
Closes #2364 - Add Rerouting of Tasks in JAVA-API
1 parent 24fb36a commit cac955b

File tree

12 files changed

+1070
-2
lines changed

12 files changed

+1070
-2
lines changed

common/taskana-common/src/main/java/pro/taskana/common/internal/util/ObjectAttributeChangeDetector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public static <T> String determineChangesInAttributes(T oldObject, T newObject)
4040

4141
// this has to be checked after we deal with List data types, because
4242
// we want to allow different implementations of the List interface to work as well.
43-
if (!oldObject.getClass().equals(newObject.getClass())) {
43+
if (!oldObject.getClass().equals(newObject.getClass())
44+
&& !oldObject.getClass().isAssignableFrom(newObject.getClass())) {
4445
throw new SystemException(
4546
String.format(
4647
"The classes differ between the oldObject(%s) and newObject(%s). "

history/taskana-simplehistory-provider/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
</dependency>
3838

3939
<!-- test dependencies -->
40+
<dependency>
41+
<groupId>pro.taskana</groupId>
42+
<artifactId>taskana-test-api</artifactId>
43+
<version>${project.version}</version>
44+
<scope>test</scope>
45+
</dependency>
4046
<dependency>
4147
<groupId>pro.taskana</groupId>
4248
<artifactId>taskana-common-data</artifactId>
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
package acceptance.events.task;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import acceptance.events.task.CreateHistoryEventOnTaskRerouteAccTest.TaskRoutingProviderForDomainA;
6+
import java.lang.reflect.Field;
7+
import java.util.List;
8+
import org.apache.ibatis.session.SqlSessionManager;
9+
import org.json.JSONArray;
10+
import org.json.JSONObject;
11+
import org.junit.jupiter.api.BeforeAll;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.ExtendWith;
14+
import pro.taskana.classification.api.ClassificationService;
15+
import pro.taskana.classification.api.models.ClassificationSummary;
16+
import pro.taskana.common.api.TaskanaEngine;
17+
import pro.taskana.common.test.security.JaasExtension;
18+
import pro.taskana.common.test.security.WithAccessId;
19+
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
20+
import pro.taskana.simplehistory.impl.TaskHistoryQueryImpl;
21+
import pro.taskana.simplehistory.impl.TaskanaHistoryEngineImpl;
22+
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
23+
import pro.taskana.spi.history.api.TaskanaHistory;
24+
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
25+
import pro.taskana.spi.history.api.events.task.TaskHistoryEventType;
26+
import pro.taskana.spi.routing.api.TaskRoutingProvider;
27+
import pro.taskana.task.api.TaskService;
28+
import pro.taskana.task.api.models.Task;
29+
import pro.taskana.testapi.DefaultTestEntities;
30+
import pro.taskana.testapi.TaskanaInject;
31+
import pro.taskana.testapi.TaskanaIntegrationTest;
32+
import pro.taskana.testapi.WithServiceProvider;
33+
import pro.taskana.testapi.builder.TaskBuilder;
34+
import pro.taskana.testapi.builder.WorkbasketAccessItemBuilder;
35+
import pro.taskana.workbasket.api.WorkbasketPermission;
36+
import pro.taskana.workbasket.api.WorkbasketService;
37+
import pro.taskana.workbasket.api.models.Workbasket;
38+
import pro.taskana.workbasket.api.models.WorkbasketSummary;
39+
40+
@WithServiceProvider(
41+
serviceProviderInterface = TaskRoutingProvider.class,
42+
serviceProviders = TaskRoutingProviderForDomainA.class)
43+
@WithServiceProvider(
44+
serviceProviderInterface = TaskanaHistory.class,
45+
serviceProviders = SimpleHistoryServiceImpl.class)
46+
@TaskanaIntegrationTest
47+
@ExtendWith(JaasExtension.class)
48+
class CreateHistoryEventOnTaskRerouteAccTest {
49+
@TaskanaInject TaskanaEngine taskanaEngine;
50+
@TaskanaInject TaskService taskService;
51+
@TaskanaInject WorkbasketService workbasketService;
52+
@TaskanaInject ClassificationService classificationService;
53+
ClassificationSummary classificationSummary;
54+
WorkbasketSummary domainAWorkbasketSummary;
55+
WorkbasketSummary domainBWorkbasketSummary;
56+
Task task1;
57+
Task task2;
58+
Task task3;
59+
Task task4;
60+
private SimpleHistoryServiceImpl historyService = new SimpleHistoryServiceImpl();
61+
private TaskanaHistoryEngineImpl taskanaHistoryEngine;
62+
63+
@WithAccessId(user = "admin")
64+
@BeforeAll
65+
void setUp() throws Exception {
66+
taskanaHistoryEngine = TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngine);
67+
historyService.initialize(taskanaEngine);
68+
classificationSummary =
69+
DefaultTestEntities.defaultTestClassification()
70+
.buildAndStoreAsSummary(classificationService);
71+
domainAWorkbasketSummary =
72+
DefaultTestEntities.defaultTestWorkbasket()
73+
.domain("DOMAIN_A")
74+
.buildAndStoreAsSummary(workbasketService);
75+
domainBWorkbasketSummary =
76+
DefaultTestEntities.defaultTestWorkbasket()
77+
.domain("DOMAIN_B")
78+
.buildAndStoreAsSummary(workbasketService);
79+
80+
task1 =
81+
TaskBuilder.newTask()
82+
.classificationSummary(classificationSummary)
83+
.workbasketSummary(domainAWorkbasketSummary)
84+
.primaryObjRef(DefaultTestEntities.defaultTestObjectReference().build())
85+
.buildAndStore(taskService);
86+
task2 =
87+
TaskBuilder.newTask()
88+
.classificationSummary(classificationSummary)
89+
.workbasketSummary(domainAWorkbasketSummary)
90+
.primaryObjRef(DefaultTestEntities.defaultTestObjectReference().build())
91+
.buildAndStore(taskService);
92+
task3 =
93+
TaskBuilder.newTask()
94+
.classificationSummary(classificationSummary)
95+
.workbasketSummary(domainBWorkbasketSummary)
96+
.primaryObjRef(DefaultTestEntities.defaultTestObjectReference().build())
97+
.buildAndStore(taskService);
98+
99+
task4 =
100+
TaskBuilder.newTask()
101+
.classificationSummary(classificationSummary)
102+
.workbasketSummary(domainAWorkbasketSummary)
103+
.primaryObjRef(DefaultTestEntities.defaultTestObjectReference().build())
104+
.buildAndStore(taskService);
105+
106+
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
107+
.workbasketId(domainAWorkbasketSummary.getId())
108+
.accessId("user-1-1")
109+
.permission(WorkbasketPermission.OPEN)
110+
.permission(WorkbasketPermission.READ)
111+
.permission(WorkbasketPermission.APPEND)
112+
.buildAndStore(workbasketService);
113+
114+
WorkbasketAccessItemBuilder.newWorkbasketAccessItem()
115+
.workbasketId(domainBWorkbasketSummary.getId())
116+
.accessId("user-1-1")
117+
.permission(WorkbasketPermission.OPEN)
118+
.permission(WorkbasketPermission.READ)
119+
.permission(WorkbasketPermission.APPEND)
120+
.buildAndStore(workbasketService);
121+
}
122+
123+
@WithAccessId(user = "admin")
124+
@Test
125+
void should_CreateRerouteHistoryEvent_When_TaskIsRerouted() throws Exception {
126+
historyService.deleteHistoryEventsByTaskIds(List.of(task4.getId()));
127+
TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();
128+
List<TaskHistoryEvent> events =
129+
taskHistoryQueryMapper.queryHistoryEvents(
130+
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(task4.getId()));
131+
assertThat(events).isEmpty();
132+
taskService.rerouteTask(task4.getId());
133+
134+
events =
135+
taskHistoryQueryMapper.queryHistoryEvents(
136+
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(task4.getId()));
137+
138+
assertThat(events).hasSize(1);
139+
String eventType = events.get(0).getEventType();
140+
assertThat(eventType).isEqualTo(TaskHistoryEventType.REROUTED.getName());
141+
assertRerouteHistoryEvent(
142+
events.get(0).getId(),
143+
domainAWorkbasketSummary.getId(),
144+
domainBWorkbasketSummary.getId(),
145+
"admin");
146+
147+
historyService.deleteHistoryEventsByTaskIds(List.of(task4.getId()));
148+
}
149+
150+
@WithAccessId(user = "admin")
151+
@Test
152+
void should_CreateRerouteHistoryEvent_When_MultipleTasksAreRerouted() throws Exception {
153+
List<String> taskIds = List.of(task1.getId(), task2.getId(), task3.getId());
154+
historyService.deleteHistoryEventsByTaskIds(taskIds);
155+
TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();
156+
157+
List<TaskHistoryEvent> events =
158+
taskHistoryQueryMapper.queryHistoryEvents(
159+
(TaskHistoryQueryImpl)
160+
historyService.createTaskHistoryQuery().taskIdIn(taskIds.toArray(new String[0])));
161+
assertThat(events).isEmpty();
162+
taskService.rerouteTasks(taskIds);
163+
164+
events =
165+
taskHistoryQueryMapper.queryHistoryEvents(
166+
(TaskHistoryQueryImpl)
167+
historyService.createTaskHistoryQuery().taskIdIn(taskIds.toArray(new String[0])));
168+
169+
assertThat(events)
170+
.extracting(TaskHistoryEvent::getTaskId)
171+
.containsExactlyInAnyOrderElementsOf(taskIds);
172+
173+
for (TaskHistoryEvent event : events) {
174+
if (event.getTaskId().equals(task1.getId())) {
175+
assertRerouteHistoryEvent(
176+
event.getId(),
177+
domainAWorkbasketSummary.getId(),
178+
domainBWorkbasketSummary.getId(),
179+
"admin");
180+
} else if (event.getTaskId().equals(task2.getId())) {
181+
assertRerouteHistoryEvent(
182+
event.getId(),
183+
domainAWorkbasketSummary.getId(),
184+
domainBWorkbasketSummary.getId(),
185+
"admin");
186+
} else {
187+
assertRerouteHistoryEvent(
188+
event.getId(),
189+
domainBWorkbasketSummary.getId(),
190+
domainAWorkbasketSummary.getId(),
191+
"admin");
192+
}
193+
}
194+
}
195+
196+
TaskHistoryQueryMapper getHistoryQueryMapper()
197+
throws NoSuchFieldException, IllegalAccessException {
198+
Field sessionManagerField = TaskanaHistoryEngineImpl.class.getDeclaredField("sessionManager");
199+
sessionManagerField.setAccessible(true);
200+
SqlSessionManager sqlSessionManager =
201+
(SqlSessionManager) sessionManagerField.get(taskanaHistoryEngine);
202+
203+
return sqlSessionManager.getMapper(TaskHistoryQueryMapper.class);
204+
}
205+
206+
private void assertRerouteHistoryEvent(
207+
String eventId, String expectedOldValue, String expectedNewValue, String expectedUser)
208+
throws Exception {
209+
TaskHistoryEvent event = historyService.getTaskHistoryEvent(eventId);
210+
assertThat(event.getDetails()).isNotNull();
211+
JSONArray changes = new JSONObject(event.getDetails()).getJSONArray("changes");
212+
assertThat(changes.length()).isPositive();
213+
boolean foundField = false;
214+
for (int i = 0; i < changes.length() && !foundField; i++) {
215+
JSONObject change = changes.getJSONObject(i);
216+
if (change.get("fieldName").equals("workbasketSummary")) {
217+
foundField = true;
218+
String oldWorkbasketStr = change.get("oldValue").toString();
219+
String newWorkbasketStr = change.get("newValue").toString();
220+
Workbasket oldWorkbasket = workbasketService.getWorkbasket(expectedOldValue);
221+
assertThat(oldWorkbasketStr)
222+
.isEqualTo(JSONObject.wrap(oldWorkbasket.asSummary()).toString());
223+
Workbasket newWorkbasket = workbasketService.getWorkbasket(expectedNewValue);
224+
assertThat(newWorkbasketStr)
225+
.isEqualTo(JSONObject.wrap(newWorkbasket.asSummary()).toString());
226+
}
227+
}
228+
assertThat(foundField).describedAs("changes do not contain field 'workbasketSummary'").isTrue();
229+
230+
assertThat(event.getId()).startsWith("THI:");
231+
assertThat(event.getOldValue()).isEqualTo(expectedOldValue);
232+
assertThat(event.getNewValue()).isEqualTo(expectedNewValue);
233+
assertThat(event.getUserId()).isEqualTo(expectedUser);
234+
assertThat(event.getEventType()).isEqualTo(TaskHistoryEventType.REROUTED.getName());
235+
}
236+
237+
class TaskRoutingProviderForDomainA implements TaskRoutingProvider {
238+
239+
@Override
240+
public void initialize(TaskanaEngine taskanaEngine) {}
241+
242+
@Override
243+
public String determineWorkbasketId(Task task) {
244+
if ("DOMAIN_A".equals(task.getDomain())) {
245+
return domainBWorkbasketSummary.getId();
246+
} else if ("DOMAIN_B".equals(task.getDomain())) {
247+
return domainAWorkbasketSummary.getId();
248+
}
249+
return null;
250+
}
251+
}
252+
}

0 commit comments

Comments
 (0)