protected void generateSignalsEndpoints()

in kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java [265:362]


    protected void generateSignalsEndpoints(TemplatedGenerator.Builder templateBuilder,
            ClassOrInterfaceDeclaration template, AtomicInteger index) {
        Optional.ofNullable(signals)
                .ifPresent(signalsMap -> {
                    //using template class to the endpoints generation
                    CompilationUnit signalClazz = templateBuilder.build(context, REST_SIGNAL_TEMPLATE_NAME)
                            .compilationUnitOrThrow();

                    ClassOrInterfaceDeclaration signalTemplate = signalClazz
                            .findFirst(ClassOrInterfaceDeclaration.class)
                            .orElseThrow(() -> new NoSuchElementException("SignalResourceTemplate class not found!"));

                    MethodDeclaration signalProcessDeclaration = signalTemplate
                            .findFirst(MethodDeclaration.class, md -> md.getNameAsString().equals("signalProcess"))
                            .orElseThrow(() -> new NoSuchElementException("signalProcess method not found in SignalResourceTemplate"));

                    MethodDeclaration signalInstanceDeclaration = signalTemplate
                            .findFirst(MethodDeclaration.class, md -> md.getNameAsString().equals("signalInstance"))
                            .orElseThrow(() -> new NoSuchElementException("signalInstance method not found in SignalResourceTemplate"));

                    Collection<TriggerMetaData> startSignalTriggers = getStartSignalTriggers();

                    signalsMap.entrySet()
                            .stream()
                            .filter(e -> Objects.nonNull(e.getKey()))
                            .forEach(entry -> {
                                String signalName = entry.getKey();
                                String signalType = entry.getValue();

                                // Looking if the Process starts with the current signal
                                Optional<TriggerMetaData> startTrigger = startSignalTriggers.stream()
                                        .filter(trigger -> trigger.getName().equals(signalName))
                                        .findAny();

                                startTrigger.ifPresent(trigger -> {
                                    // Create endpoint to signal the process container to start new instances
                                    MethodDeclaration signalProcessDeclarationClone = signalProcessDeclaration.clone();

                                    BlockStmt signalProcessBody = signalProcessDeclarationClone.getBody()
                                            .orElseThrow(() -> new RuntimeException("signalProcessDeclaration doesn't have body"));

                                    MethodCallExpr setterMethod = signalProcessBody.findAll(MethodCallExpr.class, m -> m.getName().getIdentifier().contains("$SetModelMethodName$"))
                                            .stream()
                                            .findFirst()
                                            .orElseThrow(() -> new RuntimeException("signalProcessDeclaration doesn't have model setter"));

                                    if (signalType == null) {
                                        // if there's no type we should remove the payload references form the method declaration and body
                                        signalProcessDeclarationClone.getParameters()
                                                .stream()
                                                .filter(parameter -> parameter.getNameAsString().equals("data"))
                                                .findFirst()
                                                .ifPresent(Parameter::removeForced);
                                        setterMethod.removeForced();
                                    } else {
                                        String name = Optional.ofNullable((String) trigger.getNode().getMetaData().get(Metadata.MAPPING_VARIABLE)).orElseGet(trigger::getModelRef);
                                        setterMethod.setName(setterMethod.getNameAsString().replace("$SetModelMethodName$", StringUtils.ucFirst(name)));
                                    }

                                    template.addMethod(SIGNAL_METHOD_PREFFIX + signalName, Keyword.PUBLIC)
                                            .setType(signalProcessDeclarationClone.getType())
                                            .setParameters(signalProcessDeclarationClone.getParameters())
                                            .setBody(signalProcessBody)
                                            .setAnnotations(signalProcessDeclarationClone.getAnnotations());
                                });

                                // Create endpoint to signal process instances
                                MethodDeclaration signalInstanceDeclarationClone = signalInstanceDeclaration.clone();
                                BlockStmt signalInstanceBody = signalInstanceDeclarationClone.getBody()
                                        .orElseThrow(() -> new RuntimeException("signalInstanceDeclaration doesn't have body"));

                                if (signalType == null) {
                                    signalInstanceBody.findAll(NameExpr.class, nameExpr -> "data".equals(nameExpr.getNameAsString())).forEach(name -> name.replace(new NullLiteralExpr()));
                                }

                                template.addMethod(SIGNAL_METHOD_PREFFIX + index.getAndIncrement(), Keyword.PUBLIC)
                                        .setType(signalInstanceDeclarationClone.getType())
                                        // Remove data parameter ( payload ) if signalType is null
                                        .setParameters(signalType == null ? NodeList.nodeList(signalInstanceDeclarationClone.getParameter(0)) : signalInstanceDeclaration.getParameters())
                                        .setBody(signalInstanceBody)
                                        .setAnnotations(signalInstanceDeclarationClone.getAnnotations());

                                if (signalType != null) {
                                    template.findAll(ClassOrInterfaceType.class).forEach(name -> {
                                        String identifier = name.getNameAsString();
                                        name.setName(identifier.replace("$signalType$", signalType));
                                    });
                                }

                                template.findAll(StringLiteralExpr.class).forEach(vv -> {
                                    String s = vv.getValue();
                                    String interpolated = s.replace("$signalName$", signalName);
                                    interpolated = interpolated.replace("$signalPath$", sanitizeName(signalName));
                                    vv.setString(interpolated);
                                });
                            });
                });
    }