Search in sources :

Example 1 with TriggerMetaData

use of io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData in project automatiko-engine by automatiko-io.

the class FunctionFlowGenerator method generate.

public String generate() {
    CompilationUnit clazz = parse(this.getClass().getResourceAsStream("/class-templates/FunctionFlowTemplate.java"));
    clazz.setPackageDeclaration(process.getPackageName());
    clazz.addImport(modelfqcn);
    ClassOrInterfaceDeclaration template = clazz.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(() -> new IllegalStateException("Cannot find the class in FunctionFlowTemplate"));
    template.setName(functionClazzName);
    List<String> discoveredFunctions = new ArrayList<>();
    // first to initiate the function flow
    template.findFirst(MethodDeclaration.class, md -> md.getNameAsString().equals("startTemplate")).ifPresent(md -> {
        md.setName(processId.toLowerCase() + version);
        md.getBody().get().findFirst(StringLiteralExpr.class, s -> s.getValue().equals("$TypePrefix$")).ifPresent(s -> s.setValue(process.getPackageName() + "." + processId + fversion));
        if (useInjection()) {
            String trigger = functionTrigger(process);
            String filter = functionFilter(process);
            if (filter != null) {
                Matcher matcher = PARAMETER_MATCHER.matcher(filter);
                while (matcher.find()) {
                    String paramName = matcher.group(1);
                    Optional<String> value = context.getApplicationProperty(paramName);
                    if (value.isPresent()) {
                        filter = filter.replaceAll("\\{" + paramName + "\\}", value.get());
                    } else {
                        throw new IllegalArgumentException("Missing argument declared in as function filter with name '" + paramName + "'. Define it in application.properties file");
                    }
                }
            }
            annotator.withCloudEventMapping(md, trigger, filter);
        }
    });
    MethodDeclaration callTemplate = template.findFirst(MethodDeclaration.class, md -> md.getNameAsString().equals("callTemplate")).get();
    discoveredFunctions.add(definedFunctionTrigger(process));
    // for each "execution" node add new function
    for (Node node : process.getNodesRecursively()) {
        if (isExecutionNode(node)) {
            discoveredFunctions.add(definedFunctionTrigger(node));
            MethodDeclaration flowStepFunction = callTemplate.clone();
            if (useInjection()) {
                String trigger = functionTrigger(node);
                String filter = functionFilter(node);
                if (filter != null) {
                    Matcher matcher = PARAMETER_MATCHER.matcher(filter);
                    while (matcher.find()) {
                        String paramName = matcher.group(1);
                        Optional<String> value = context.getApplicationProperty(paramName);
                        if (value.isPresent() && !value.get().isEmpty()) {
                            filter = filter.replaceAll("\\{" + paramName + "\\}", value.get());
                        } else {
                            throw new IllegalArgumentException("Missing argument declared in as function filter with name '" + paramName + "'. Define it in application.properties file");
                        }
                    }
                }
                annotator.withCloudEventMapping(flowStepFunction, trigger, filter);
            }
            flowStepFunction.getBody().get().findFirst(StringLiteralExpr.class, s -> s.getValue().equals("$StartFromNode$")).ifPresent(s -> s.setValue((String) node.getMetaData().get("UniqueId")));
            flowStepFunction.getBody().get().findFirst(StringLiteralExpr.class, s -> s.getValue().equals("$TypePrefix$")).ifPresent(s -> s.setValue(process.getPackageName() + "." + processId + fversion + "."));
            flowStepFunction.getBody().get().findFirst(StringLiteralExpr.class, s -> s.getValue().equals("$ThisNode$")).ifPresent(s -> s.setValue(node.getName()));
            flowStepFunction.setName(sanitizeIdentifier(node.getName() + version).toLowerCase());
            template.addMember(flowStepFunction);
        } else if (node instanceof EndNode || node instanceof FaultNode) {
            discoveredFunctions.add(definedFunctionTrigger(node));
        }
    }
    // remove the template method
    callTemplate.removeForced();
    // process signals
    MethodDeclaration signalTemplate = template.findFirst(MethodDeclaration.class, md -> md.getNameAsString().equals("signalTemplate")).get();
    Optional.ofNullable(signals).ifPresent(signalsMap -> {
        AtomicInteger index = new AtomicInteger(0);
        signalsMap.entrySet().stream().filter(e -> Objects.nonNull(e.getKey())).forEach(entry -> {
            String signalName = entry.getKey();
            String signalType = entry.getValue();
            MethodDeclaration flowSignalFunction = produceSignalFunction("", signalName, signalType, signalTemplate, index, signalNodes.get(signalName));
            template.addMember(flowSignalFunction);
        });
    });
    if (triggers != null && !triggers.isEmpty()) {
        AtomicInteger index = new AtomicInteger(0);
        for (TriggerMetaData trigger : triggers) {
            if (trigger.getType().equals(TriggerMetaData.TriggerType.ConsumeMessage)) {
                String signalName = trigger.getName();
                String signalType = trigger.getDataType();
                MethodDeclaration flowSignalFunction = produceSignalFunction("Message-", signalName, signalType, signalTemplate, index, (Node) trigger.getContext("_node_"));
                VariableDeclarationExpr correlationVar = flowSignalFunction.findFirst(VariableDeclarationExpr.class, vd -> vd.getVariable(0).getNameAsString().equals("correlation")).get();
                if (trigger.getCorrelation() != null) {
                    correlationVar.getVariable(0).setInitializer(new StringLiteralExpr(trigger.getCorrelation()));
                } else if (trigger.getCorrelationExpression() != null) {
                    correlationVar.getVariable(0).setInitializer(new NameExpr(trigger.getCorrelationExpression()));
                }
                template.addMember(flowSignalFunction);
            }
        }
    }
    // remove the template method
    signalTemplate.removeForced();
    Map<String, String> typeInterpolations = new HashMap<>();
    typeInterpolations.put("$Clazz$", functionClazzName);
    typeInterpolations.put("$Type$", dataClazzName);
    template.findAll(ClassOrInterfaceType.class).forEach(cls -> interpolateTypes(cls, typeInterpolations));
    if (useInjection()) {
        template.findAll(FieldDeclaration.class, CodegenUtils::isProcessField).forEach(fd -> annotator.withNamedInjection(fd, processId + version));
        template.findAll(FieldDeclaration.class, CodegenUtils::isApplicationField).forEach(fd -> annotator.withInjection(fd));
        template.findAll(FieldDeclaration.class, CodegenUtils::isIdentitySupplierField).forEach(fd -> annotator.withInjection(fd));
        template.findAll(FieldDeclaration.class, CodegenUtils::isEventSourceField).forEach(fd -> annotator.withInjection(fd));
        template.findAll(MethodDeclaration.class, md -> md.isPublic()).forEach(md -> annotator.withFunction(md));
    }
    NodeList<Expression> items = NodeList.nodeList(discoveredFunctions.stream().map(s -> new StringLiteralExpr(s)).collect(Collectors.toList()));
    template.addAnnotation(new NormalAnnotationExpr(new Name(Generated.class.getCanonicalName()), NodeList.nodeList(new MemberValuePair("value", new ArrayInitializerExpr(items)), new MemberValuePair("reference", new StringLiteralExpr(context.getApplicationProperty("quarkus.google.cloud.project-id").orElse("missing"))), new MemberValuePair("name", new StringLiteralExpr(StringUtils.capitalize(ProcessToExecModelGenerator.extractProcessId(processId, version)))), new MemberValuePair("hidden", new BooleanLiteralExpr(false)))));
    template.getMembers().sort(new BodyDeclarationComparator());
    ImportsOrganizer.organize(clazz);
    return clazz.toString();
}
Also used : SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) ClassOrInterfaceType(com.github.javaparser.ast.type.ClassOrInterfaceType) ProcessToExecModelGenerator(io.automatiko.engine.workflow.compiler.canonical.ProcessToExecModelGenerator) RuleSetNode(io.automatiko.engine.workflow.process.core.node.RuleSetNode) StaticJavaParser.parse(com.github.javaparser.StaticJavaParser.parse) Name(com.github.javaparser.ast.expr.Name) GeneratorContext(io.automatiko.engine.codegen.GeneratorContext) HashMap(java.util.HashMap) Node(io.automatiko.engine.api.definition.process.Node) ArrayList(java.util.ArrayList) Matcher(java.util.regex.Matcher) CodegenUtils.interpolateTypes(io.automatiko.engine.codegen.CodegenUtils.interpolateTypes) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) StringUtils(io.automatiko.engine.services.utils.StringUtils) Expression(com.github.javaparser.ast.expr.Expression) CompilationUnit(com.github.javaparser.ast.CompilationUnit) TriggerMetaData(io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData) DependencyInjectionAnnotator(io.automatiko.engine.codegen.di.DependencyInjectionAnnotator) CodegenUtils(io.automatiko.engine.codegen.CodegenUtils) NodeList(com.github.javaparser.ast.NodeList) BooleanLiteralExpr(com.github.javaparser.ast.expr.BooleanLiteralExpr) WorkflowProcess(io.automatiko.engine.api.definition.process.WorkflowProcess) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) BodyDeclarationComparator(io.automatiko.engine.codegen.BodyDeclarationComparator) FaultNode(io.automatiko.engine.workflow.process.core.node.FaultNode) NameExpr(com.github.javaparser.ast.expr.NameExpr) Collectors(java.util.stream.Collectors) NormalAnnotationExpr(com.github.javaparser.ast.expr.NormalAnnotationExpr) StringLiteralExpr(com.github.javaparser.ast.expr.StringLiteralExpr) VariableDeclarationExpr(com.github.javaparser.ast.expr.VariableDeclarationExpr) Objects(java.util.Objects) List(java.util.List) FieldDeclaration(com.github.javaparser.ast.body.FieldDeclaration) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) MemberValuePair(com.github.javaparser.ast.expr.MemberValuePair) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) Optional(java.util.Optional) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) Pattern(java.util.regex.Pattern) ArrayInitializerExpr(com.github.javaparser.ast.expr.ArrayInitializerExpr) ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) Generated(io.automatiko.engine.api.codegen.Generated) ImportsOrganizer(io.automatiko.engine.codegen.ImportsOrganizer) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) Matcher(java.util.regex.Matcher) HashMap(java.util.HashMap) SubProcessNode(io.automatiko.engine.workflow.process.core.node.SubProcessNode) RuleSetNode(io.automatiko.engine.workflow.process.core.node.RuleSetNode) Node(io.automatiko.engine.api.definition.process.Node) BoundaryEventNode(io.automatiko.engine.workflow.process.core.node.BoundaryEventNode) ActionNode(io.automatiko.engine.workflow.process.core.node.ActionNode) FaultNode(io.automatiko.engine.workflow.process.core.node.FaultNode) WorkItemNode(io.automatiko.engine.workflow.process.core.node.WorkItemNode) StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) EventNode(io.automatiko.engine.workflow.process.core.node.EventNode) ArrayList(java.util.ArrayList) StringLiteralExpr(com.github.javaparser.ast.expr.StringLiteralExpr) NameExpr(com.github.javaparser.ast.expr.NameExpr) ClassOrInterfaceType(com.github.javaparser.ast.type.ClassOrInterfaceType) FieldDeclaration(com.github.javaparser.ast.body.FieldDeclaration) Name(com.github.javaparser.ast.expr.Name) MemberValuePair(com.github.javaparser.ast.expr.MemberValuePair) ArrayInitializerExpr(com.github.javaparser.ast.expr.ArrayInitializerExpr) BooleanLiteralExpr(com.github.javaparser.ast.expr.BooleanLiteralExpr) BodyDeclarationComparator(io.automatiko.engine.codegen.BodyDeclarationComparator) NormalAnnotationExpr(com.github.javaparser.ast.expr.NormalAnnotationExpr) CompilationUnit(com.github.javaparser.ast.CompilationUnit) VariableDeclarationExpr(com.github.javaparser.ast.expr.VariableDeclarationExpr) Generated(io.automatiko.engine.api.codegen.Generated) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) TriggerMetaData(io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData) FaultNode(io.automatiko.engine.workflow.process.core.node.FaultNode) EndNode(io.automatiko.engine.workflow.process.core.node.EndNode) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Expression(com.github.javaparser.ast.expr.Expression)

Example 2 with TriggerMetaData

use of io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData 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;
}
Also used : ObjectCreationExpr(com.github.javaparser.ast.expr.ObjectCreationExpr) ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) SvgBpmnProcessImageGenerator(io.automatiko.engine.codegen.process.image.SvgBpmnProcessImageGenerator) SimpleName(com.github.javaparser.ast.expr.SimpleName) NameExpr(com.github.javaparser.ast.expr.NameExpr) StringLiteralExpr(com.github.javaparser.ast.expr.StringLiteralExpr) SvgServerlessProcessImageGenerator(io.automatiko.engine.codegen.process.image.SvgServerlessProcessImageGenerator) ClassOrInterfaceType(com.github.javaparser.ast.type.ClassOrInterfaceType) FieldDeclaration(com.github.javaparser.ast.body.FieldDeclaration) VariableDeclarator(com.github.javaparser.ast.body.VariableDeclarator) AssignExpr(com.github.javaparser.ast.expr.AssignExpr) ConstructorDeclaration(com.github.javaparser.ast.body.ConstructorDeclaration) CastExpr(com.github.javaparser.ast.expr.CastExpr) BodyDeclarationComparator(io.automatiko.engine.codegen.BodyDeclarationComparator) FieldAccessExpr(com.github.javaparser.ast.expr.FieldAccessExpr) ThisExpr(com.github.javaparser.ast.expr.ThisExpr) MethodDeclaration(com.github.javaparser.ast.body.MethodDeclaration) BlockStmt(com.github.javaparser.ast.stmt.BlockStmt) TriggerMetaData(io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData) WorkItemHandler(io.automatiko.engine.api.runtime.process.WorkItemHandler) SvgProcessImageGenerator(io.automatiko.engine.codegen.process.image.SvgProcessImageGenerator) EndOfInstanceStrategy(io.automatiko.engine.api.workflow.EndOfInstanceStrategy) ProcessMetaData(io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData) Parameter(com.github.javaparser.ast.body.Parameter) ReturnStmt(com.github.javaparser.ast.stmt.ReturnStmt) MethodCallExpr(com.github.javaparser.ast.expr.MethodCallExpr)

Example 3 with TriggerMetaData

use of io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData in project automatiko-engine by automatiko-io.

the class ProcessCodegen method generate.

public List<GeneratedFile> generate() {
    if (processes.isEmpty()) {
        return Collections.emptyList();
    }
    List<ProcessGenerator> ps = new ArrayList<>();
    List<ProcessInstanceGenerator> pis = new ArrayList<>();
    List<ProcessExecutableModelGenerator> processExecutableModelGenerators = new ArrayList<>();
    // REST resources
    List<AbstractResourceGenerator> rgs = new ArrayList<>();
    // GraphQL resources
    List<AbstractResourceGenerator> grapggs = new ArrayList<>();
    // Function resources
    List<FunctionGenerator> fgs = new ArrayList<>();
    // Function flow resources
    List<FunctionFlowGenerator> ffgs = new ArrayList<>();
    // message data events
    List<MessageDataEventGenerator> mdegs = new ArrayList<>();
    // message endpoints/consumers
    Set<MessageConsumerGenerator> megs = new LinkedHashSet<>();
    // message producers
    List<MessageProducerGenerator> mpgs = new ArrayList<>();
    // OpenAPI clients
    Set<OpenAPIClientGenerator> opgs = new LinkedHashSet<>();
    List<String> publicProcesses = new ArrayList<>();
    Map<String, ModelMetaData> processIdToModel = new HashMap<>();
    Map<String, ModelClassGenerator> processIdToModelGenerator = new HashMap<>();
    Map<String, InputModelClassGenerator> processIdToInputModelGenerator = new HashMap<>();
    Map<String, OutputModelClassGenerator> processIdToOutputModelGenerator = new HashMap<>();
    Map<String, List<UserTaskModelMetaData>> processIdToUserTaskModel = new HashMap<>();
    Map<String, ProcessMetaData> processIdToMetadata = new HashMap<>();
    String workflowType = Process.WORKFLOW_TYPE;
    if (isFunctionFlowProject()) {
        workflowType = Process.FUNCTION_FLOW_TYPE;
    } else if (isFunctionProject()) {
        workflowType = Process.FUNCTION_TYPE;
    }
    // then we can instantiate the exec model generator
    // with the data classes that we have already resolved
    ProcessToExecModelGenerator execModelGenerator = new ProcessToExecModelGenerator(contextClassLoader, workflowType);
    // first we generate all the data classes from variable declarations
    for (Entry<String, WorkflowProcess> entry : processes.entrySet()) {
        ModelClassGenerator mcg = new ModelClassGenerator(execModelGenerator, context(), entry.getValue());
        processIdToModelGenerator.put(entry.getKey(), mcg);
        processIdToModel.put(entry.getKey(), mcg.generate());
        InputModelClassGenerator imcg = new InputModelClassGenerator(context(), entry.getValue(), workflowType);
        processIdToInputModelGenerator.put(entry.getKey(), imcg);
        OutputModelClassGenerator omcg = new OutputModelClassGenerator(context(), entry.getValue(), workflowType);
        processIdToOutputModelGenerator.put(entry.getKey(), omcg);
        context.addGenerator("ModelClassGenerator", entry.getKey(), mcg);
        context.addGenerator("InputModelClassGenerator", entry.getKey(), imcg);
        context.addGenerator("OutputModelClassGenerator", entry.getKey(), omcg);
    }
    // then we generate user task inputs and outputs if any
    for (Entry<String, WorkflowProcess> entry : processes.entrySet()) {
        UserTasksModelClassGenerator utcg = new UserTasksModelClassGenerator(entry.getValue(), context);
        processIdToUserTaskModel.put(entry.getKey(), utcg.generate());
    }
    List<String> functions = context.getBuildContext().classThatImplement(Functions.class.getCanonicalName());
    // collect all process descriptors (exec model)
    for (Entry<String, WorkflowProcess> entry : processes.entrySet()) {
        ProcessExecutableModelGenerator execModelGen = new ProcessExecutableModelGenerator(entry.getValue(), execModelGenerator);
        String packageName = entry.getValue().getPackageName();
        String id = entry.getKey();
        // add extra meta data to indicate if user task mgmt is available
        if (context.getBuildContext().isUserTaskMgmtSupported()) {
            entry.getValue().getMetaData().put("UserTaskMgmt", "true");
        }
        Set<String> classImports = ((io.automatiko.engine.workflow.process.core.WorkflowProcess) entry.getValue()).getImports();
        if (classImports != null) {
            classImports = new HashSet<>();
            ((io.automatiko.engine.workflow.process.core.WorkflowProcess) entry.getValue()).setImports(classImports);
        }
        classImports.add(BaseFunctions.class.getCanonicalName());
        classImports.addAll(functions);
        try {
            ProcessMetaData generate = execModelGen.generate();
            processIdToMetadata.put(id, generate);
            processExecutableModelGenerators.add(execModelGen);
            context.addProcess(id, generate);
        } catch (RuntimeException e) {
            LOGGER.error(e.getMessage());
            throw new ProcessCodegenException(id, packageName, e);
        }
    }
    // generate Process, ProcessInstance classes and the REST resource
    for (ProcessExecutableModelGenerator execModelGen : processExecutableModelGenerators) {
        String classPrefix = StringUtils.capitalize(execModelGen.extractedProcessId());
        WorkflowProcess workFlowProcess = execModelGen.process();
        ModelClassGenerator modelClassGenerator = processIdToModelGenerator.get(execModelGen.getProcessId());
        ProcessGenerator p = new ProcessGenerator(context, workFlowProcess, execModelGen, classPrefix, modelClassGenerator.className(), applicationCanonicalName, processIdToUserTaskModel.get(execModelGen.getProcessId()), processIdToMetadata).withDependencyInjection(annotator).withPersistence(persistence);
        ProcessInstanceGenerator pi = new ProcessInstanceGenerator(workflowType, context(), execModelGen, workFlowProcess.getPackageName(), classPrefix, modelClassGenerator.generate());
        ProcessMetaData metaData = processIdToMetadata.get(execModelGen.getProcessId());
        if (isFunctionFlowProject()) {
            ffgs.add(new FunctionFlowGenerator(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName).withDependencyInjection(annotator).withSignals(metaData.getSignals(), metaData.getSignalNodes()).withTriggers(metaData.getTriggers()));
            if (metaData.getTriggers() != null) {
                for (TriggerMetaData trigger : metaData.getTriggers()) {
                    if (trigger.getType().equals(TriggerMetaData.TriggerType.ProduceMessage)) {
                        MessageDataEventGenerator msgDataEventGenerator = new MessageDataEventGenerator(workFlowProcess, trigger).withDependencyInjection(annotator);
                        mdegs.add(msgDataEventGenerator);
                        mpgs.add(new MessageProducerGenerator(workflowType, context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), msgDataEventGenerator.className(), trigger).withDependencyInjection(annotator));
                    }
                }
            }
        } else if (isFunctionProject()) {
            fgs.add(new FunctionGenerator(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName).withDependencyInjection(annotator));
        } else if (isServiceProject()) {
            if (isPublic(workFlowProcess)) {
                // Creating and adding the ResourceGenerator
                resourceGeneratorFactory.create(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName).map(r -> r.withDependencyInjection(annotator).withParentProcess(null).withPersistence(persistence).withUserTasks(processIdToUserTaskModel.get(execModelGen.getProcessId())).withPathPrefix("{id}").withSignals(metaData.getSignals()).withTriggers(metaData.isStartable(), metaData.isDynamic()).withSubProcesses(populateSubprocesses(workFlowProcess, processIdToMetadata.get(execModelGen.getProcessId()), processIdToMetadata, processIdToModelGenerator, processExecutableModelGenerators, processIdToUserTaskModel))).ifPresent(rgs::add);
                if (context.getBuildContext().isGraphQLSupported()) {
                    GraphQLResourceGenerator graphqlGenerator = new GraphQLResourceGenerator(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName);
                    graphqlGenerator.withDependencyInjection(annotator).withParentProcess(null).withPersistence(persistence).withUserTasks(processIdToUserTaskModel.get(execModelGen.getProcessId())).withPathPrefix(CodegenUtils.version(workFlowProcess.getVersion())).withSignals(metaData.getSignals()).withTriggers(metaData.isStartable(), metaData.isDynamic()).withSubProcesses(populateSubprocessesGraphQL(workFlowProcess, processIdToMetadata.get(execModelGen.getProcessId()), processIdToMetadata, processIdToModelGenerator, processExecutableModelGenerators, processIdToUserTaskModel));
                    grapggs.add(graphqlGenerator);
                }
            }
            if (metaData.getTriggers() != null) {
                for (TriggerMetaData trigger : metaData.getTriggers()) {
                    // generate message consumers for processes with message events
                    if (isPublic(workFlowProcess) && trigger.getType().equals(TriggerMetaData.TriggerType.ConsumeMessage)) {
                        MessageDataEventGenerator msgDataEventGenerator = new MessageDataEventGenerator(workFlowProcess, trigger).withDependencyInjection(annotator);
                        mdegs.add(msgDataEventGenerator);
                        megs.add(new MessageConsumerGenerator(context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), applicationCanonicalName, msgDataEventGenerator.className(), trigger).withDependencyInjection(annotator).withPersistence(persistence));
                    } else if (trigger.getType().equals(TriggerMetaData.TriggerType.ProduceMessage)) {
                        MessageDataEventGenerator msgDataEventGenerator = new MessageDataEventGenerator(workFlowProcess, trigger).withDependencyInjection(annotator);
                        mdegs.add(msgDataEventGenerator);
                        mpgs.add(new MessageProducerGenerator(workflowType, context(), workFlowProcess, modelClassGenerator.className(), execModelGen.className(), msgDataEventGenerator.className(), trigger).withDependencyInjection(annotator));
                    }
                }
            }
        }
        if (metaData.getOpenAPIs() != null) {
            for (OpenAPIMetaData api : metaData.getOpenAPIs()) {
                OpenAPIClientGenerator oagenerator = new OpenAPIClientGenerator(context, workFlowProcess, api).withDependencyInjection(annotator);
                opgs.add(oagenerator);
            }
        }
        moduleGenerator.addProcess(p);
        ps.add(p);
        pis.add(pi);
    }
    for (ModelClassGenerator modelClassGenerator : processIdToModelGenerator.values()) {
        ModelMetaData mmd = modelClassGenerator.generate();
        storeFile(Type.MODEL, modelClassGenerator.generatedFilePath(), mmd.generate(annotator != null ? new String[] { "io.quarkus.runtime.annotations.RegisterForReflection" } : new String[0]));
    }
    for (InputModelClassGenerator modelClassGenerator : processIdToInputModelGenerator.values()) {
        ModelMetaData mmd = modelClassGenerator.generate();
        storeFile(Type.MODEL, modelClassGenerator.generatedFilePath(), mmd.generate(annotator != null ? new String[] { "io.quarkus.runtime.annotations.RegisterForReflection" } : new String[0]));
    }
    for (OutputModelClassGenerator modelClassGenerator : processIdToOutputModelGenerator.values()) {
        ModelMetaData mmd = modelClassGenerator.generate();
        storeFile(Type.MODEL, modelClassGenerator.generatedFilePath(), mmd.generate(annotator != null ? new String[] { "io.quarkus.runtime.annotations.RegisterForReflection" } : new String[0]));
    }
    for (List<UserTaskModelMetaData> utmd : processIdToUserTaskModel.values()) {
        for (UserTaskModelMetaData ut : utmd) {
            storeFile(Type.MODEL, UserTasksModelClassGenerator.generatedFilePath(ut.getInputModelClassName()), ut.generateInput());
            storeFile(Type.MODEL, UserTasksModelClassGenerator.generatedFilePath(ut.getOutputModelClassName()), ut.generateOutput());
        }
    }
    for (AbstractResourceGenerator resourceGenerator : rgs) {
        storeFile(Type.REST, resourceGenerator.generatedFilePath(), resourceGenerator.generate());
    }
    for (AbstractResourceGenerator resourceGenerator : grapggs) {
        storeFile(Type.GRAPHQL, resourceGenerator.generatedFilePath(), resourceGenerator.generate());
    }
    for (FunctionGenerator functionGenerator : fgs) {
        storeFile(Type.FUNCTION, functionGenerator.generatedFilePath(), functionGenerator.generate());
    }
    for (FunctionFlowGenerator functionFlowGenerator : ffgs) {
        storeFile(Type.FUNCTION_FLOW, functionFlowGenerator.generatedFilePath(), functionFlowGenerator.generate());
    }
    for (MessageDataEventGenerator messageDataEventGenerator : mdegs) {
        storeFile(Type.CLASS, messageDataEventGenerator.generatedFilePath(), messageDataEventGenerator.generate());
    }
    for (MessageConsumerGenerator messageConsumerGenerator : megs) {
        storeFile(Type.MESSAGE_CONSUMER, messageConsumerGenerator.generatedFilePath(), messageConsumerGenerator.generate());
    }
    for (MessageProducerGenerator messageProducerGenerator : mpgs) {
        storeFile(Type.MESSAGE_PRODUCER, messageProducerGenerator.generatedFilePath(), messageProducerGenerator.generate());
    }
    for (OpenAPIClientGenerator openApiClientGenerator : opgs) {
        openApiClientGenerator.generate();
        Map<String, String> contents = openApiClientGenerator.generatedClasses();
        for (Entry<String, String> entry : contents.entrySet()) {
            storeFile(Type.CLASS, entry.getKey().replace('.', '/') + ".java", entry.getValue());
        }
    }
    for (ProcessGenerator p : ps) {
        storeFile(Type.PROCESS, p.generatedFilePath(), p.generate());
        p.getAdditionalClasses().forEach(cp -> {
            String packageName = cp.getPackageDeclaration().map(pd -> pd.getName().toString()).orElse("");
            String clazzName = cp.findFirst(ClassOrInterfaceDeclaration.class).map(cls -> cls.getName().toString()).get();
            String path = (packageName + "." + clazzName).replace('.', '/') + ".java";
            storeFile(Type.CLASS, path, cp.toString());
        });
    }
    for (ProcessInstanceGenerator pi : pis) {
        storeFile(Type.PROCESS_INSTANCE, pi.generatedFilePath(), pi.generate());
    }
    for (ProcessExecutableModelGenerator processGenerator : processExecutableModelGenerators) {
        if (processGenerator.isPublic()) {
            publicProcesses.add(processGenerator.extractedProcessId());
        }
    }
    return generatedFiles;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Arrays(java.util.Arrays) Enumeration(java.util.Enumeration) XmlProcessReader(io.automatiko.engine.workflow.compiler.xml.XmlProcessReader) Type(io.automatiko.engine.codegen.GeneratedFile.Type) LoggerFactory(org.slf4j.LoggerFactory) ApplicationSection(io.automatiko.engine.codegen.ApplicationSection) ApplicationGenerator.log(io.automatiko.engine.codegen.ApplicationGenerator.log) DefaultResourceGeneratorFactory(io.automatiko.engine.codegen.DefaultResourceGeneratorFactory) Resource(io.automatiko.engine.api.io.Resource) Map(java.util.Map) ZipFile(java.util.zip.ZipFile) TriggerMetaData(io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData) DependencyInjectionAnnotator(io.automatiko.engine.codegen.di.DependencyInjectionAnnotator) Path(java.nio.file.Path) ZipEntry(java.util.zip.ZipEntry) Process(io.automatiko.engine.api.definition.process.Process) BPMNExtensionsSemanticModule(io.automatiko.engine.workflow.bpmn2.xml.BPMNExtensionsSemanticModule) Collection(java.util.Collection) Set(java.util.Set) Collectors(java.util.stream.Collectors) ByteArrayResource(io.automatiko.engine.services.io.ByteArrayResource) StandardCharsets(java.nio.charset.StandardCharsets) InternalResource(io.automatiko.engine.services.io.InternalResource) UncheckedIOException(java.io.UncheckedIOException) List(java.util.List) Stream(java.util.stream.Stream) BPMNDISemanticModule(io.automatiko.engine.workflow.bpmn2.xml.BPMNDISemanticModule) SAXException(org.xml.sax.SAXException) Entry(java.util.Map.Entry) ResourceType.determineResourceType(io.automatiko.engine.api.io.ResourceType.determineResourceType) Optional(java.util.Optional) ModelMetaData(io.automatiko.engine.workflow.compiler.canonical.ModelMetaData) ClassOrInterfaceDeclaration(com.github.javaparser.ast.body.ClassOrInterfaceDeclaration) ResourceGeneratorFactory(io.automatiko.engine.codegen.ResourceGeneratorFactory) ProcessToExecModelGenerator(io.automatiko.engine.workflow.compiler.canonical.ProcessToExecModelGenerator) SemanticModules(io.automatiko.engine.workflow.compiler.xml.SemanticModules) ServerlessWorkflowParser(io.automatiko.engine.workflow.serverless.parser.ServerlessWorkflowParser) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) IoUtils.readBytesFromInputStream(io.automatiko.engine.services.utils.IoUtils.readBytesFromInputStream) StringUtils(io.automatiko.engine.services.utils.StringUtils) ResourceType(io.automatiko.engine.api.io.ResourceType) FileSystemResource(io.automatiko.engine.services.io.FileSystemResource) LinkedHashSet(java.util.LinkedHashSet) UserTaskModelMetaData(io.automatiko.engine.workflow.compiler.canonical.UserTaskModelMetaData) CodegenUtils(io.automatiko.engine.codegen.CodegenUtils) BaseFunctions(io.automatiko.engine.services.execution.BaseFunctions) ConfigGenerator(io.automatiko.engine.codegen.ConfigGenerator) GeneratedFile(io.automatiko.engine.codegen.GeneratedFile) Logger(org.slf4j.Logger) Files(java.nio.file.Files) ApplicationGenerator(io.automatiko.engine.codegen.ApplicationGenerator) WorkflowProcess(io.automatiko.engine.api.definition.process.WorkflowProcess) IOException(java.io.IOException) ProcessConfigGenerator(io.automatiko.engine.codegen.process.config.ProcessConfigGenerator) BPMNSemanticModule(io.automatiko.engine.workflow.bpmn2.xml.BPMNSemanticModule) File(java.io.File) OpenAPIMetaData(io.automatiko.engine.workflow.compiler.canonical.OpenAPIMetaData) ProcessMetaData(io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData) Paths(java.nio.file.Paths) AbstractGenerator(io.automatiko.engine.codegen.AbstractGenerator) Functions(io.automatiko.engine.api.Functions) Collections(java.util.Collections) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) WorkflowProcess(io.automatiko.engine.api.definition.process.WorkflowProcess) UserTaskModelMetaData(io.automatiko.engine.workflow.compiler.canonical.UserTaskModelMetaData) ProcessToExecModelGenerator(io.automatiko.engine.workflow.compiler.canonical.ProcessToExecModelGenerator) BaseFunctions(io.automatiko.engine.services.execution.BaseFunctions) Functions(io.automatiko.engine.api.Functions) TriggerMetaData(io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData) ModelMetaData(io.automatiko.engine.workflow.compiler.canonical.ModelMetaData) UserTaskModelMetaData(io.automatiko.engine.workflow.compiler.canonical.UserTaskModelMetaData) BaseFunctions(io.automatiko.engine.services.execution.BaseFunctions) ProcessMetaData(io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData) OpenAPIMetaData(io.automatiko.engine.workflow.compiler.canonical.OpenAPIMetaData)

Aggregations

ClassOrInterfaceDeclaration (com.github.javaparser.ast.body.ClassOrInterfaceDeclaration)3 TriggerMetaData (io.automatiko.engine.workflow.compiler.canonical.TriggerMetaData)3 FieldDeclaration (com.github.javaparser.ast.body.FieldDeclaration)2 MethodDeclaration (com.github.javaparser.ast.body.MethodDeclaration)2 NameExpr (com.github.javaparser.ast.expr.NameExpr)2 StringLiteralExpr (com.github.javaparser.ast.expr.StringLiteralExpr)2 ClassOrInterfaceType (com.github.javaparser.ast.type.ClassOrInterfaceType)2 WorkflowProcess (io.automatiko.engine.api.definition.process.WorkflowProcess)2 BodyDeclarationComparator (io.automatiko.engine.codegen.BodyDeclarationComparator)2 CodegenUtils (io.automatiko.engine.codegen.CodegenUtils)2 DependencyInjectionAnnotator (io.automatiko.engine.codegen.di.DependencyInjectionAnnotator)2 ProcessMetaData (io.automatiko.engine.workflow.compiler.canonical.ProcessMetaData)2 StaticJavaParser.parse (com.github.javaparser.StaticJavaParser.parse)1 CompilationUnit (com.github.javaparser.ast.CompilationUnit)1 NodeList (com.github.javaparser.ast.NodeList)1 ConstructorDeclaration (com.github.javaparser.ast.body.ConstructorDeclaration)1 Parameter (com.github.javaparser.ast.body.Parameter)1 VariableDeclarator (com.github.javaparser.ast.body.VariableDeclarator)1 ArrayInitializerExpr (com.github.javaparser.ast.expr.ArrayInitializerExpr)1 AssignExpr (com.github.javaparser.ast.expr.AssignExpr)1