use of io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData in project automatiko-engine by automatiko-io.
the class GeneratorContext method collectRelatedProcesses.
protected void collectRelatedProcesses(Set<File> outcome, Set<ProcessMetaData> relatedProcesses) {
// add all related process source files
relatedProcesses.forEach(pm -> outcome.add(new File(pm.getSource())));
// next check if any of the processes has subprocess
for (ProcessMetaData metadata : relatedProcesses) {
if (metadata.getSubProcesses() != null && !metadata.getSubProcesses().isEmpty()) {
Set<ProcessMetaData> subpocesses = metadata.getSubProcesses().entrySet().stream().map(entry -> this.processes.get(entry.getKey())).collect(Collectors.toSet());
collectRelatedProcesses(outcome, subpocesses);
}
}
}
use of io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData in project automatiko-engine by automatiko-io.
the class ProcessCodegen method populateSubprocesses.
protected List<AbstractResourceGenerator> populateSubprocesses(WorkflowProcess parentProcess, ProcessMetaData metaData, Map<String, ProcessMetaData> processIdToMetadata, Map<String, ModelClassGenerator> processIdToModelGenerator, List<ProcessExecutableModelGenerator> processExecutableModelGenerators, Map<String, List<UserTaskModelMetaData>> processIdToUserTaskModel) {
List<AbstractResourceGenerator> subprocesses = new ArrayList<AbstractResourceGenerator>();
for (Entry<String, String> entry : metaData.getSubProcesses().entrySet()) {
ProcessExecutableModelGenerator execModelGen = processExecutableModelGenerators.stream().filter(p -> p.getProcessId().equals(entry.getValue())).findFirst().orElse(null);
if (execModelGen != null) {
WorkflowProcess workFlowProcess = execModelGen.process();
ModelClassGenerator modelClassGenerator = processIdToModelGenerator.get(entry.getValue());
Optional.of(new SubprocessResourceGenerator(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName)).map(r -> r.withDependencyInjection(annotator).withParentProcess(parentProcess).withUserTasks(processIdToUserTaskModel.get(execModelGen.getProcessId())).withSignals(processIdToMetadata.get(execModelGen.getProcessId()).getSignals()).withTriggers(processIdToMetadata.get(execModelGen.getProcessId()).isStartable(), processIdToMetadata.get(execModelGen.getProcessId()).isDynamic()).withSubProcesses(populateSubprocesses(workFlowProcess, processIdToMetadata.get(execModelGen.getProcessId()), processIdToMetadata, processIdToModelGenerator, processExecutableModelGenerators, processIdToUserTaskModel))).ifPresent(subprocesses::add);
}
}
return subprocesses;
}
use of io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData in project automatiko-engine by automatiko-io.
the class ProcessGenerator method internalConfigure.
private MethodDeclaration internalConfigure(ProcessMetaData processMetaData) {
BlockStmt body = new BlockStmt();
MethodDeclaration internalConfigure = new MethodDeclaration().setModifiers(Modifier.Keyword.PUBLIC).setType(targetTypeName).setName("configure").setBody(body);
// always call super.configure
body.addStatement(new MethodCallExpr(new SuperExpr(), "configure"));
if (!processMetaData.getGeneratedHandlers().isEmpty()) {
processMetaData.getGeneratedHandlers().forEach((name, descriptor) -> {
CompilationUnit handler = descriptor.generateHandlerClassForService();
ClassOrInterfaceDeclaration clazz = handler.findFirst(ClassOrInterfaceDeclaration.class).get();
if (useInjection()) {
boolean tracingAvailable = context.getBuildContext().hasClassAvailable("org.eclipse.microprofile.opentracing.Traced");
if (tracingAvailable) {
FieldDeclaration tracerField = new FieldDeclaration().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, "io.automatiko.engine.service.tracing.TracingAdds"), "tracer"));
annotator.withInjection(tracerField);
clazz.addMember(tracerField);
clazz.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("executeWorkItem")).forEach(md -> {
// add Traced nnotation on method level
md.addAnnotation("org.eclipse.microprofile.opentracing.Traced");
// next update method body to include extra tags
BlockStmt mbody = md.getBody().get();
MethodCallExpr tracer = new MethodCallExpr(new NameExpr("tracer"), "addTags").addArgument(new MethodCallExpr(new NameExpr("workItem"), "getProcessInstance"));
BlockStmt updatedBody = new BlockStmt();
updatedBody.addStatement(tracer);
mbody.getStatements().forEach(s -> updatedBody.addStatement(s));
md.setBody(updatedBody);
});
}
boolean faultToleranceAvailable = context.getBuildContext().hasClassAvailable("io.automatiko.addons.fault.tolerance.CircuitClosedEvent");
if (faultToleranceAvailable) {
Boolean disabled = Boolean.parseBoolean(descriptor.metadata("faultToleranceDisabled", "false").toString());
if (!disabled) {
Long timeout = Long.valueOf(descriptor.metadata("timeout", "-1").toString());
Long delay = Long.valueOf(descriptor.metadata("delay", "5000").toString());
Integer threshold = Integer.valueOf(descriptor.metadata("requestThreshold", "20").toString());
Double ratio = Double.valueOf(descriptor.metadata("failureRatio", ".50").toString());
NormalAnnotationExpr circuitBrakerAnnotation = new NormalAnnotationExpr(new Name("org.eclipse.microprofile.faulttolerance.CircuitBreaker"), NodeList.nodeList(new MemberValuePair("delay", new LongLiteralExpr(delay)), new MemberValuePair("requestVolumeThreshold", new IntegerLiteralExpr(threshold)), new MemberValuePair("failureRatio", new DoubleLiteralExpr(ratio)), new MemberValuePair("skipOn", new NameExpr("io.automatiko.engine.api.workflow.HandledServiceExecutionError.class"))));
clazz.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("executeWorkItem")).forEach(md -> {
// add CircuitBreaker annotation on method level
md.addAnnotation(circuitBrakerAnnotation);
md.addSingleMemberAnnotation("io.smallrye.faulttolerance.api.CircuitBreakerName", new StringLiteralExpr(name));
if (timeout > 0) {
md.addSingleMemberAnnotation("org.eclipse.microprofile.faulttolerance.Timeout", new LongLiteralExpr(timeout));
}
});
context.setApplicationProperty("quarkus.arc.selected-alternatives", context.getApplicationProperty("quarkus.arc.selected-alternatives").filter(s -> !s.contains("io.automatiko.addons.fault.tolerance.internal.AutomatikoStrategyCache")).map(s -> s + ",io.automatiko.addons.fault.tolerance.internal.AutomatikoStrategyCache").orElse("io.automatiko.addons.fault.tolerance.internal.AutomatikoStrategyCache"));
}
}
annotator.withApplicationComponent(clazz);
} else {
String packageName = handler.getPackageDeclaration().map(pd -> pd.getName().toString()).orElse("");
String clazzName = clazz.getName().toString();
MethodCallExpr workItemManager = new MethodCallExpr(new NameExpr("services"), "getWorkItemManager");
MethodCallExpr registerHandler = new MethodCallExpr(workItemManager, "registerWorkItemHandler").addArgument(new StringLiteralExpr(name)).addArgument(new ObjectCreationExpr(null, new ClassOrInterfaceType(null, packageName + "." + clazzName), NodeList.nodeList()));
body.addStatement(registerHandler);
}
// annotate for injection or add constructor for initialization
handler.findAll(FieldDeclaration.class, fd -> !fd.getVariable(0).getNameAsString().equals("tracer")).forEach(fd -> {
if (useInjection()) {
annotator.withInjection(fd);
}
if (descriptor.implementation().equalsIgnoreCase("##webservice") && !fd.getVariable(0).getNameAsString().equals("completionHandler") && annotator != null) {
annotator.withRestClientInjection(fd);
} else if (!descriptor.implementation().equalsIgnoreCase("##webservice") && !fd.getVariable(0).getNameAsString().equals("completionHandler")) {
BlockStmt constructorBody = new BlockStmt();
AssignExpr assignExpr = new AssignExpr(new FieldAccessExpr(new ThisExpr(), fd.getVariable(0).getNameAsString()), new ObjectCreationExpr().setType(fd.getVariable(0).getType().toString()), AssignExpr.Operator.ASSIGN);
constructorBody.addStatement(assignExpr);
clazz.addConstructor(Keyword.PUBLIC).setBody(constructorBody);
}
});
additionalClasses.add(handler);
});
if (useInjection()) {
BlockStmt actionBody = new BlockStmt();
LambdaExpr forachBody = new LambdaExpr(new Parameter(new UnknownType(), "h"), actionBody);
MethodCallExpr forachHandler = new MethodCallExpr(new NameExpr("handlers"), "forEach");
forachHandler.addArgument(forachBody);
MethodCallExpr workItemManager = new MethodCallExpr(new NameExpr("services"), "getWorkItemManager");
MethodCallExpr registerHandler = new MethodCallExpr(workItemManager, "registerWorkItemHandler").addArgument(new MethodCallExpr(new NameExpr("h"), "getName")).addArgument(new NameExpr("h"));
actionBody.addStatement(registerHandler);
body.addStatement(forachHandler);
}
}
if (!processMetaData.getGeneratedListeners().isEmpty()) {
processMetaData.getGeneratedListeners().forEach(listener -> {
ClassOrInterfaceDeclaration clazz = listener.findFirst(ClassOrInterfaceDeclaration.class).get();
String packageName = listener.getPackageDeclaration().map(pd -> pd.getName().toString()).orElse("");
String clazzName = clazz.getName().toString();
MethodCallExpr eventSupport = new MethodCallExpr(new NameExpr("services"), "getEventSupport");
MethodCallExpr registerListener = new MethodCallExpr(eventSupport, "addEventListener").addArgument(new ObjectCreationExpr(null, new ClassOrInterfaceType(null, packageName + "." + clazzName), NodeList.nodeList()));
body.addStatement(registerListener);
additionalClasses.add(listener);
});
}
body.addStatement(new ReturnStmt(new ThisExpr()));
return internalConfigure;
}
use of io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData in project automatiko-engine by automatiko-io.
the class ProcessGenerator method classDeclaration.
public ClassOrInterfaceDeclaration classDeclaration(CompilationUnit compilationUnit) {
ClassOrInterfaceDeclaration cls = new ClassOrInterfaceDeclaration().setName(targetTypeName).setModifiers(Modifier.Keyword.PUBLIC);
if (useInjection()) {
annotator.withNamedApplicationComponent(cls, process.getId() + versionSuffix);
FieldDeclaration handlersInjectFieldDeclaration = new FieldDeclaration().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, new SimpleName(annotator.multiInstanceInjectionType()), NodeList.nodeList(new ClassOrInterfaceType(null, WorkItemHandler.class.getCanonicalName()))), "handlers"));
cls.addMember(handlersInjectFieldDeclaration);
}
String processInstanceFQCN = ProcessInstanceGenerator.qualifiedName(packageName, typeName);
FieldDeclaration fieldDeclaration = new FieldDeclaration().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, appCanonicalName), "app"));
ConstructorDeclaration emptyConstructorDeclaration = new ConstructorDeclaration().setName(targetTypeName).addModifier(Modifier.Keyword.PUBLIC);
ConstructorDeclaration baseConstructorDeclaration = new ConstructorDeclaration().setName(targetTypeName).addModifier(Modifier.Keyword.PUBLIC).addParameter(appCanonicalName, "app").setBody(new BlockStmt().addStatement(new MethodCallExpr(null, "super").addArgument(new MethodCallExpr(new MethodCallExpr(new NameExpr("app"), "config"), "process"))).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "app"), new NameExpr("app"), AssignExpr.Operator.ASSIGN)));
ConstructorDeclaration constructorDeclaration;
if (useInjection()) {
constructorDeclaration = new ConstructorDeclaration().setName(targetTypeName).addModifier(Modifier.Keyword.PUBLIC).addParameter(appCanonicalName, "app").addParameter(new ClassOrInterfaceType(null, new SimpleName(annotator.multiInstanceInjectionType()), NodeList.nodeList(new ClassOrInterfaceType(null, WorkItemHandler.class.getCanonicalName()))), "handlers").addParameter(EndOfInstanceStrategy.class.getCanonicalName(), "strategy").setBody(new BlockStmt().addStatement(new MethodCallExpr(null, "super").addArgument(new MethodCallExpr(new MethodCallExpr(new NameExpr("app"), "config"), "process"))).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "app"), new NameExpr("app"), AssignExpr.Operator.ASSIGN)).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "handlers"), new NameExpr("handlers"), AssignExpr.Operator.ASSIGN)).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "endOfInstanceStrategy"), new NameExpr("strategy"), AssignExpr.Operator.ASSIGN)));
} else {
constructorDeclaration = new ConstructorDeclaration().setName(targetTypeName).addModifier(Modifier.Keyword.PUBLIC).addParameter(appCanonicalName, "app").addParameter(EndOfInstanceStrategy.class.getCanonicalName(), "strategy").setBody(new BlockStmt().addStatement(new MethodCallExpr(null, "super").addArgument(new MethodCallExpr(new MethodCallExpr(new NameExpr("app"), "config"), "process"))).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "app"), new NameExpr("app"), AssignExpr.Operator.ASSIGN)).addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), "endOfInstanceStrategy"), new NameExpr("strategy"), AssignExpr.Operator.ASSIGN)));
}
ProcessMetaData processMetaData = processGenerator.generate();
if (!processMetaData.getSubProcesses().isEmpty()) {
for (Entry<String, String> subProcess : processMetaData.getSubProcesses().entrySet()) {
FieldDeclaration subprocessFieldDeclaration = new FieldDeclaration();
if (processIdToMetadata.get(subProcess.getKey()) != null) {
String subProcessPackage = processIdToMetadata.get(subProcess.getKey()).getPackageName();
if (subProcessPackage != null && !subProcessPackage.isEmpty()) {
compilationUnit.addImport(subProcessPackage + "." + StringUtils.capitalize(subProcess.getKey() + "Model"));
}
}
String fieldName = "process" + subProcess.getKey();
ClassOrInterfaceType modelType = new ClassOrInterfaceType(null, new SimpleName(io.automatiko.engine.api.workflow.Process.class.getCanonicalName()), NodeList.nodeList(new ClassOrInterfaceType(null, StringUtils.capitalize(subProcess.getKey() + "Model"))));
if (useInjection()) {
subprocessFieldDeclaration.addVariable(new VariableDeclarator(modelType, fieldName));
constructorDeclaration.addParameter(annotator.withNamed(new Parameter(modelType, fieldName), subProcess.getKey()));
constructorDeclaration.getBody().addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), fieldName), new NameExpr(fieldName), AssignExpr.Operator.ASSIGN));
} else {
// app.processes().processById()
MethodCallExpr initSubProcessField = new MethodCallExpr(new MethodCallExpr(new NameExpr("app"), "processes"), "processById").addArgument(new StringLiteralExpr(subProcess.getKey()));
subprocessFieldDeclaration.addVariable(new VariableDeclarator(modelType, fieldName));
baseConstructorDeclaration.getBody().addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), fieldName), new CastExpr(modelType, initSubProcessField), Operator.ASSIGN));
constructorDeclaration.getBody().addStatement(new AssignExpr(new FieldAccessExpr(new ThisExpr(), fieldName), new CastExpr(modelType, initSubProcessField), Operator.ASSIGN));
}
cls.addMember(subprocessFieldDeclaration);
subprocessFieldDeclaration.createGetter();
}
}
if (useInjection()) {
annotator.withInjection(constructorDeclaration);
} else {
emptyConstructorDeclaration.setBody(new BlockStmt().addStatement(new MethodCallExpr(null, "this").addArgument(new ObjectCreationExpr().setType(appCanonicalName))));
}
MethodDeclaration createModelMethod = new MethodDeclaration().addModifier(Keyword.PUBLIC).setName("createModel").setType(modelTypeName).setBody(new BlockStmt().addStatement(new ReturnStmt(new ObjectCreationExpr(null, new ClassOrInterfaceType(null, modelTypeName), NodeList.nodeList()))));
cls.addExtendedType(abstractProcessType(modelTypeName)).addMember(fieldDeclaration).addMember(emptyConstructorDeclaration).addMember(baseConstructorDeclaration).addMember(constructorDeclaration).addMember(createInstanceMethod(processInstanceFQCN)).addMember(createInstanceWithBusinessKeyMethod(processInstanceFQCN)).addMember(createModelMethod).addMember(createInstanceGenericMethod(processInstanceFQCN)).addMember(createInstanceGenericWithBusinessKeyMethod(processInstanceFQCN)).addMember(createInstanceGenericWithWorkflowInstanceMethod(processInstanceFQCN)).addMember(createReadOnlyInstanceGenericWithWorkflowInstanceMethod(processInstanceFQCN)).addMember(internalConfigure(processMetaData)).addMember(internalRegisterListeners(processMetaData)).addMember(userTaskInputModels(processMetaData)).addMember(userTaskOutputModels(processMetaData)).addMember(process(processMetaData));
if (isServiceProject()) {
SvgProcessImageGenerator imageGenerator = isServerlessWorkflow() ? new SvgServerlessProcessImageGenerator(process) : new SvgBpmnProcessImageGenerator(process);
String svg = imageGenerator.generate();
if (svg != null && !svg.isEmpty()) {
MethodDeclaration processImageMethod = new MethodDeclaration().setName("image").setModifiers(Keyword.PUBLIC).setType(String.class).setBody(new BlockStmt().addStatement(new ReturnStmt(new StringLiteralExpr().setString(svg))));
cls.addMember(processImageMethod);
}
}
if (useInjection()) {
MethodDeclaration initMethod = annotator.withInitMethod(new MethodCallExpr(new ThisExpr(), "activate"));
cls.addMember(initMethod);
}
if (!processMetaData.getTriggers().isEmpty()) {
for (TriggerMetaData trigger : processMetaData.getTriggers()) {
// add message produces as field
if (trigger.getType().equals(TriggerMetaData.TriggerType.ProduceMessage)) {
String producerFieldType = packageName + "." + typeName + "MessageProducer_" + trigger.getOwnerId();
String producerFielName = "producer_" + trigger.getOwnerId();
FieldDeclaration producerFieldieldDeclaration = new FieldDeclaration().addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, producerFieldType), producerFielName));
cls.addMember(producerFieldieldDeclaration);
if (useInjection()) {
annotator.withInjection(producerFieldieldDeclaration);
} else {
AssignExpr assignExpr = new AssignExpr(new FieldAccessExpr(new ThisExpr(), producerFielName), new ObjectCreationExpr().setType(producerFieldType), AssignExpr.Operator.ASSIGN);
cls.getConstructors().forEach(c -> c.getBody().addStatement(assignExpr));
}
}
}
}
cls.getMembers().sort(new BodyDeclarationComparator());
return cls;
}
use of io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData in project automatiko-engine by automatiko-io.
the class ProcessInstanceGenerator method classDeclaration.
public ClassOrInterfaceDeclaration classDeclaration() {
ClassOrInterfaceDeclaration classDecl = new ClassOrInterfaceDeclaration().setName(targetTypeName).addModifier(Modifier.Keyword.PUBLIC);
classDecl.addExtendedType(new ClassOrInterfaceType(null, AbstractProcessInstance.class.getCanonicalName()).setTypeArguments(new ClassOrInterfaceType(null, model.getModelClassSimpleName()))).addMember(constructorDecl()).addMember(constructorWithBusinessKeyDecl()).addMember(constructorWithWorkflowInstanceAndRuntimeDecl()).addMember(constructorWorkflowInstanceDecl()).addMember(bind()).addMember(unbind());
if (generatorContext.getApplicationProperty("quarkus.automatiko.instance-locking").orElse("true").equalsIgnoreCase("false")) {
MethodDeclaration configureLock = new MethodDeclaration().setModifiers(Keyword.PROTECTED).setName("configureLock").addParameter(String.class.getCanonicalName(), "businessKey").setType(new VoidType());
classDecl.addMember(configureLock);
}
ProcessMetaData processMetaData = processGenerator.generate();
if (!processMetaData.getSubProcesses().isEmpty()) {
classDecl.getMembers().add(subprocessesMethod(processMetaData));
}
classDecl.getMembers().sort(new BodyDeclarationComparator());
return classDecl;
}
Aggregations