Skip to content

Commit

Permalink
[KOGITO-4502] GET task id API to return task info, not only the input
Browse files Browse the repository at this point in the history
model
  • Loading branch information
fjtirado committed Apr 22, 2021
1 parent fea3d18 commit 1267859
Show file tree
Hide file tree
Showing 22 changed files with 1,004 additions and 347 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public interface WorkItem {

String getId();

default String getNodeId() {
throw new UnsupportedOperationException();
}

String getNodeInstanceId();

String getName();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.kogito.process.workitem;

/**
* Process view of a work item.<br>
* It includes only parameters and results as defined in process plus getters to get the active phase.<br>
*
* @param <P> Input generated class
* @param <R> Output generated class
*/
public interface TaskModel<P, R> {

String getId();

String getName();

int getState();

String getPhase();

String getPhaseStatus();

P getParameters();

R getResults();
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ void testSaveTask() {
.statusCode(200)
.extract()
.as(Map.class));

assertEquals(true, given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("processId", processId)
.pathParam("taskId", taskId)
.get("/approvals/{processId}/firstLineApproval/{taskId}")
.then()
.statusCode(200)
.extract()
.path("results.approved"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.kie.kogito.integrationtests.springboot;

import java.util.Collections;

import java.util.HashMap;
import java.util.Map;

Expand All @@ -26,7 +27,7 @@
import org.acme.examples.model.Rating;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.kie.kogito.process.WorkItem;
import org.kie.kogito.process.workitem.TaskModel;
import org.kie.kogito.testcontainers.springboot.InfinispanSpringBootTestResource;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
Expand Down Expand Up @@ -66,7 +67,7 @@ void testSubmitMovie() {
.extract()
.path("id");

WorkItem task = given()
TaskModel task = given()
.when()
.get("/cinema/{pid}/tasks", pid)
.then()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ void testSaveTask() {
.statusCode(200)
.extract()
.as(Map.class));

assertEquals(true , given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
.pathParam("processId", processId)
.pathParam("taskId", taskId)
.get("/approvals/{processId}/firstLineApproval/{taskId}")
.then()
.statusCode(200)
.extract()
.path("results.approved"));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
package org.kie.kogito.integrationtests.springboot;

import java.util.Map;
import org.kie.kogito.process.workitem.TaskModel;

import org.kie.kogito.process.WorkItem;


public class TestWorkItem implements WorkItem {
public class TestWorkItem implements TaskModel<Map<String,Object>,Map<String,Object>> {
/*
* It is interesting to have an implementation of WorkItem for testing that
* the information returned by REST API is consistent with the interface definition.
Expand All @@ -30,7 +29,6 @@ public class TestWorkItem implements WorkItem {
*/

private String id;
private String nodeInstanceId;
private String name;
private int state;
private String phase;
Expand All @@ -46,14 +44,6 @@ public void setId(String id) {
this.id = id;
}

public String getNodeInstanceId() {
return nodeInstanceId;
}

public void setNodeInstanceId(String nodeInstanceId) {
this.nodeInstanceId = nodeInstanceId;
}

public String getName() {
return name;
}
Expand Down Expand Up @@ -101,6 +91,4 @@ public Map<String, Object> getResults() {
public void setResults(Map<String, Object> results) {
this.results = results;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.comments.LineComment;
import com.github.javaparser.ast.expr.AssignExpr;
Expand All @@ -52,9 +54,13 @@
import com.github.javaparser.ast.expr.StringLiteralExpr;
import com.github.javaparser.ast.expr.ThisExpr;
import com.github.javaparser.ast.expr.VariableDeclarationExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithType;
import com.github.javaparser.ast.nodeTypes.NodeWithVariables;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.ast.stmt.SwitchEntry;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.Type;

import static com.github.javaparser.StaticJavaParser.parse;
import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
Expand All @@ -66,6 +72,7 @@ public class UserTaskModelMetaData {

private static final String TASK_INTPUT_CLASS_SUFFIX = "TaskInput";
private static final String TASK_OUTTPUT_CLASS_SUFFIX = "TaskOutput";
private static final String TASK_MODEL_CLASS_SUFFIX = "TaskModel";
private static final String TASK_NAME = "TaskName";
private static final String WORK_ITEM = "workItem";
private static final String PARAMS = "params";
Expand All @@ -85,6 +92,9 @@ public class UserTaskModelMetaData {
private String outputModelClassName;
private String outputModelClassSimpleName;

private String taskModelClassName;
private String taskModelClassSimpleName;

public UserTaskModelMetaData(String packageName, VariableScope processVariableScope, VariableScope variableScope, HumanTaskNode humanTaskNode, String processId) {
this.packageName = packageName;
this.processVariableScope = processVariableScope;
Expand All @@ -98,6 +108,9 @@ public UserTaskModelMetaData(String packageName, VariableScope processVariableSc
this.outputModelClassSimpleName = ucFirst(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + humanTaskNode.getId() + "_" + TASK_OUTTPUT_CLASS_SUFFIX);
this.outputModelClassName = packageName + '.' + outputModelClassSimpleName;

this.taskModelClassSimpleName = ucFirst(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + humanTaskNode.getId() + "_" + TASK_MODEL_CLASS_SUFFIX);
this.taskModelClassName = packageName + '.' + taskModelClassSimpleName;

}

public String generateInput() {
Expand All @@ -110,36 +123,21 @@ public String generateOutput() {
return modelClass.toString();
}

public String getInputModelClassName() {
return inputModelClassName;
}

public void setInputModelClassName(String inputModelClassName) {
this.inputModelClassName = inputModelClassName;
}

public String getInputModelClassSimpleName() {
return inputModelClassSimpleName;
public String generateModel() {
CompilationUnit modelClass = compilationUnitModel();
return modelClass.toString();
}

public void setInputModelClassSimpleName(String inputModelClassSimpleName) {
this.inputModelClassSimpleName = inputModelClassSimpleName;
public String getInputModelClassName() {
return inputModelClassName;
}

public String getOutputModelClassName() {
return outputModelClassName;
}

public void setOutputModelClassName(String outputModelClassName) {
this.outputModelClassName = outputModelClassName;
}

public String getOutputModelClassSimpleName() {
return outputModelClassSimpleName;
}

public void setOutputModelClassSimpleName(String outputModelClassSimpleName) {
this.outputModelClassSimpleName = outputModelClassSimpleName;
public String getTaskModelClassName() {
return taskModelClassName;
}

public String getName() {
Expand All @@ -166,18 +164,17 @@ private void addUserTaskParamAnnotation(FieldDeclaration fd, UserTaskParam.Param
fd.addAndGetAnnotation(UserTaskParam.class).addPair("value", ParamType.class.getSimpleName() + '.' + paramType);
}

private RuntimeException cannotFindClass() {
return new IllegalStateException("Cannot find class declaration in the template");
}

private CompilationUnit compilationUnitInput() {
// task input handling
CompilationUnit compilationUnit = parse(this.getClass().getResourceAsStream("/class-templates/TaskInputTemplate.java"));
compilationUnit.setPackageDeclaration(packageName);
Optional<ClassOrInterfaceDeclaration> processMethod = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class, sl1 -> true);

if (!processMethod.isPresent()) {
throw new RuntimeException("Cannot find class declaration in the template");
}
ClassOrInterfaceDeclaration modelClass = processMethod.get();
compilationUnit.addOrphanComment(new LineComment("Task input model for user task '" + humanTaskNode.getName() + "' in process '" + processId + "'"));

ClassOrInterfaceDeclaration modelClass = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class,
sl1 -> true).orElseThrow(this::cannotFindClass);
addComment(compilationUnit, "Task input");
addUserTaskAnnotation(modelClass);

modelClass.setName(inputModelClassSimpleName);
Expand All @@ -188,21 +185,6 @@ private CompilationUnit compilationUnitInput() {
VariableDeclarationExpr itemField = new VariableDeclarationExpr(modelType, "item");
staticFromMap.addStatement(new AssignExpr(itemField, new ObjectCreationExpr(null, modelType, NodeList.nodeList()), AssignExpr.Operator.ASSIGN));
NameExpr item = new NameExpr("item");
FieldAccessExpr idField = new FieldAccessExpr(item, "_id");
staticFromMap.addStatement(new AssignExpr(idField, new MethodCallExpr(
new NameExpr(WORK_ITEM), "getId"), AssignExpr.Operator.ASSIGN));

FieldAccessExpr nameField = new FieldAccessExpr(item, "_name");
staticFromMap.addStatement(new AssignExpr(nameField, new MethodCallExpr(
new NameExpr(WORK_ITEM), "getName"), AssignExpr.Operator.ASSIGN));

ClassOrInterfaceType toMap = new ClassOrInterfaceType(null, new SimpleName(Map.class.getSimpleName()),
NodeList.nodeList(new ClassOrInterfaceType(null, String.class.getSimpleName()), new ClassOrInterfaceType(
null,
Object.class.getSimpleName())));
VariableDeclarationExpr paramsField = new VariableDeclarationExpr(toMap, PARAMS);
staticFromMap.addStatement(new AssignExpr(paramsField, new MethodCallExpr(
new NameExpr(WORK_ITEM), "getParameters"), AssignExpr.Operator.ASSIGN));

for (Entry<String, String> entry : humanTaskNode.getInMappings().entrySet()) {

Expand Down Expand Up @@ -271,7 +253,7 @@ private CompilationUnit compilationUnitInput() {
AssignExpr.Operator.ASSIGN));
}
Optional<MethodDeclaration> staticFromMethod = modelClass.findFirst(
MethodDeclaration.class, sl -> sl.getName().asString().equals("from") && sl.isStatic());
MethodDeclaration.class, sl -> sl.getName().asString().equals("fromMap") && sl.isStatic());
if (staticFromMethod.isPresent()) {
MethodDeclaration from = staticFromMethod.get();
from.setType(modelClass.getNameAsString());
Expand All @@ -285,11 +267,8 @@ private CompilationUnit compilationUnitInput() {
private CompilationUnit compilationUnitOutput() {
CompilationUnit compilationUnit = parse(this.getClass().getResourceAsStream("/class-templates/TaskOutputTemplate.java"));
compilationUnit.setPackageDeclaration(packageName);
ClassOrInterfaceDeclaration modelClass = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class,
sl1 -> true).orElseThrow(
() -> new IllegalStateException(
"Cannot find class declaration in the template"));
compilationUnit.addOrphanComment(new LineComment("Task output model for user task '" + humanTaskNode.getName() + "' in process '" + processId + "'"));
ClassOrInterfaceDeclaration modelClass = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class, sl1 -> true).orElseThrow(this::cannotFindClass);
addComment(compilationUnit, "Task output");
addUserTaskAnnotation(modelClass);
modelClass.setName(outputModelClassSimpleName);

Expand Down Expand Up @@ -370,8 +349,62 @@ private CompilationUnit compilationUnitOutput() {
return compilationUnit;
}

private CompilationUnit compilationUnitModel() {
CompilationUnit compilationUnit = parse(this.getClass().getResourceAsStream(
"/class-templates/TaskModelTemplate.java"));
compilationUnit.setPackageDeclaration(packageName);
ClassOrInterfaceDeclaration modelClass = compilationUnit
.findFirst(ClassOrInterfaceDeclaration.class, sl1 -> true).orElseThrow(this::cannotFindClass);
addComment(compilationUnit, "Task model");
modelClass.setName(taskModelClassSimpleName);
modelClass.getImplementedTypes().forEach(t -> t
.setTypeArguments(
NodeList.nodeList(parseClassOrInterfaceType(inputModelClassName), parseClassOrInterfaceType(
outputModelClassName))));
modelClass.findAll(NameExpr.class).forEach(this::templateReplacement);
modelClass.findAll(VariableDeclarationExpr.class).forEach(this::templateReplacement);
modelClass.findAll(FieldDeclaration.class).forEach(this::templateReplacement);
modelClass.findAll(ObjectCreationExpr.class).forEach(this::templateReplacement);
modelClass.findAll(MethodDeclaration.class).forEach(this::templateReplacement);
modelClass.findAll(Parameter.class).forEach(this::templateReplacement);
return compilationUnit;
}

private void addComment(CompilationUnit unit, String prefix) {
unit.addOrphanComment(new LineComment(prefix + " for user task '" + humanTaskNode.getName() + "' in process '" + processId + "'"));
}

private void templateReplacement(NameExpr name) {
name.setName(templateReplacement(name.getNameAsString()));
}

private <T extends Node, R extends Type> void templateReplacement(NodeWithType<T, R> expr) {
expr.setType(templateReplacement(expr.getTypeAsString()));
}

private <T extends Node> void templateReplacement(NodeWithVariables<T> expr) {
for (VariableDeclarator variable : expr.getVariables()) {
variable.setType(templateReplacement(variable.getTypeAsString()));
}
}

public String templateReplacement(String template) {
template = template.replace("$TaskInput$", inputModelClassName);
template = template.replace("$TaskOutput$", outputModelClassName);
template = template.replace("$TaskModel$", taskModelClassName);
return template;
}

public boolean isAdHoc() {
return !Boolean.parseBoolean((String) humanTaskNode.getMetaData(CUSTOM_AUTO_START))
&& (humanTaskNode.getIncomingConnections() == null || humanTaskNode.getIncomingConnections().isEmpty());
}

public SwitchEntry getModelSwitchEntry() {
SwitchEntry entry = new SwitchEntry();
entry.setLabels(NodeList.nodeList(new StringLiteralExpr(Long.toString(humanTaskNode.getId()))));
entry.addStatement(new ReturnStmt(new MethodCallExpr(new NameExpr(
taskModelClassSimpleName), new SimpleName("from")).addArgument(WORK_ITEM)));
return entry;
}
}
Loading

0 comments on commit 1267859

Please sign in to comment.