use of io.automatiko.engine.codegen.CodegenUtils 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();
}
use of io.automatiko.engine.codegen.CodegenUtils in project automatiko-engine by automatiko-io.
the class FunctionGenerator method generate.
public String generate() {
CompilationUnit clazz = parse(this.getClass().getResourceAsStream("/class-templates/FunctionTemplate.java"));
clazz.setPackageDeclaration(process.getPackageName());
clazz.addImport(modelfqcn);
ClassOrInterfaceDeclaration template = clazz.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(() -> new IllegalStateException("Cannot find the class in FunctionTemplate"));
template.setName(functionClazzName);
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.findFirst(MethodDeclaration.class, md -> md.isPublic()).ifPresent(md -> {
annotator.withFunction(md);
md.setName(processId);
});
}
template.getMembers().sort(new BodyDeclarationComparator());
ImportsOrganizer.organize(clazz);
return clazz.toString();
}
use of io.automatiko.engine.codegen.CodegenUtils in project automatiko-engine by automatiko-io.
the class AbstractResourceGenerator method generateCompilationUnit.
public CompilationUnit generateCompilationUnit() {
CompilationUnit clazz = parse(this.getClass().getResourceAsStream(getResourceTemplate()));
clazz.setPackageDeclaration(process.getPackageName());
clazz.addImport(modelfqcn);
ClassOrInterfaceDeclaration template = clazz.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(() -> new NoSuchElementException("Compilation unit doesn't contain a class or interface declaration!"));
template.setName(resourceClazzName);
AtomicInteger index = new AtomicInteger(0);
AtomicInteger uindex = new AtomicInteger(0);
// Generate signals endpoints
Optional.ofNullable(signals).ifPresent(signalsMap -> {
// using template class to the endpoints generation
CompilationUnit signalClazz = parse(this.getClass().getResourceAsStream(getSignalResourceTemplate()));
ClassOrInterfaceDeclaration signalTemplate = signalClazz.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(() -> new NoSuchElementException("SignalResourceTemplate class not found!"));
signalsMap.entrySet().stream().filter(e -> Objects.nonNull(e.getKey())).forEach(entry -> {
String signalName = entry.getKey();
String signalType = entry.getValue();
String methodName = sanitizeName(signalName) + "_" + index.getAndIncrement();
signalTemplate.findAll(MethodDeclaration.class).forEach(md -> {
MethodDeclaration cloned = md.clone();
BlockStmt body = cloned.getBody().get();
if (signalType == null) {
body.findAll(NameExpr.class, nameExpr -> "data".equals(nameExpr.getNameAsString())).forEach(name -> name.replace(new NullLiteralExpr()));
}
template.addMethod(cloned.getNameAsString() + "_" + methodName, Keyword.PUBLIC).setType(cloned.getType()).setParameters(signalType == null ? removeLastParam(cloned) : cloned.getParameters()).setBody(body).setAnnotations(cloned.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);
});
});
});
if (userTasks != null) {
CompilationUnit userTaskClazz = parse(this.getClass().getResourceAsStream(getUserTaskResourceTemplate()));
ClassOrInterfaceDeclaration userTaskTemplate = userTaskClazz.findFirst(ClassOrInterfaceDeclaration.class).orElseThrow(() -> new NoSuchElementException("Compilation unit doesn't contain a class or interface declaration!"));
for (UserTaskModelMetaData userTask : userTasks) {
String methodSuffix = sanitizeName(userTask.getName()) + "_" + sanitizeName(processId) + "_" + uindex.getAndIncrement();
userTaskTemplate.findAll(MethodDeclaration.class).forEach(md -> {
MethodDeclaration cloned = md.clone();
template.addMethod(cloned.getName() + "_" + methodSuffix, Keyword.PUBLIC).setType(cloned.getType()).setParameters(cloned.getParameters()).setBody(cloned.getBody().get()).setAnnotations(cloned.getAnnotations());
});
template.findAll(StringLiteralExpr.class).forEach(s -> interpolateUserTaskStrings(s, userTask));
template.findAll(ClassOrInterfaceType.class).forEach(c -> interpolateUserTaskTypes(c, userTask.getInputModelClassSimpleName(), userTask.getOutputModelClassSimpleName()));
template.findAll(NameExpr.class).forEach(c -> interpolateUserTaskNameExp(c, userTask));
if (!userTask.isAdHoc()) {
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("signal_" + methodSuffix)).collect(Collectors.toList()).forEach(template::remove);
}
}
}
template.findAll(StringLiteralExpr.class).forEach(this::interpolateStrings);
Map<String, String> typeInterpolations = new HashMap<>();
typeInterpolations.put("$Clazz$", resourceClazzName);
typeInterpolations.put("$Type$", dataClazzName);
template.findAll(ClassOrInterfaceType.class).forEach(cls -> interpolateTypes(cls, typeInterpolations));
template.findAll(MethodDeclaration.class).forEach(this::interpolateMethods);
template.findAll(ConstructorDeclaration.class).forEach(this::interpolateConstructor);
template.findAll(FieldDeclaration.class).forEach(this::interpolateFields);
template.findAll(NameExpr.class).forEach(this::interpolateVariables);
template.findAll(MethodCallExpr.class).forEach(this::interpolateMethodCall);
if (useInjection()) {
template.findAll(FieldDeclaration.class, CodegenUtils::isProcessField).stream().filter(fd -> fd.getVariable(0).getNameAsString().startsWith("subprocess_")).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));
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);
template.addMember(tracerField);
template.findAll(MethodDeclaration.class, md -> md.getNameAsString().equals("tracing")).forEach(md -> {
BlockStmt body = new BlockStmt();
body.addStatement(new MethodCallExpr(new NameExpr("tracer"), "addTags").addArgument(new NameExpr("intance")));
md.setBody(body);
});
}
} else {
template.findAll(FieldDeclaration.class, CodegenUtils::isProcessField).forEach(this::initializeProcessField);
template.findAll(FieldDeclaration.class, CodegenUtils::isApplicationField).forEach(this::initializeApplicationField);
}
// trigger to start process instances
if (!startable || !isPublic()) {
Optional<MethodDeclaration> createResourceMethod = template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("create_" + processName)).findFirst();
createResourceMethod.ifPresent(template::remove);
}
for (AbstractResourceGenerator resourceGenerator : subprocesses) {
resourceGenerator.withPathPrefix(parentProcess == null ? pathPrefix : pathPrefix + "/" + processId + "/{id_" + processId + "}");
CompilationUnit subunit = resourceGenerator.generateCompilationUnit();
subunit.findFirst(ClassOrInterfaceDeclaration.class).get().findAll(MethodDeclaration.class).forEach(md -> {
MethodDeclaration cloned = md.clone();
interpolateMethodParams(cloned);
Optional<AnnotationExpr> pathAnotation = cloned.getAnnotationByName("Path");
if (pathAnotation.isPresent()) {
String v = pathAnotation.get().toString().replaceAll("\\{id", "#{id");
Matcher matcher = PatternConstants.PARAMETER_MATCHER.matcher(v);
while (matcher.find()) {
String paramName = matcher.group(1);
if (cloned.getParameterByName(paramName).isEmpty()) {
cloned.addParameter(new Parameter().setName(paramName).setType(String.class).addAnnotation(new SingleMemberAnnotationExpr(new Name("javax.ws.rs.PathParam"), new StringLiteralExpr(paramName))));
}
}
}
cloned.getParameters().sort(new Comparator<Parameter>() {
@Override
public int compare(Parameter o1, Parameter o2) {
if (o1.getAnnotations().isEmpty() && o1.getAnnotations().isEmpty()) {
return 0;
} else if (o1.getAnnotations().isEmpty() && !o1.getAnnotations().isEmpty()) {
return -1;
} else {
return 1;
}
}
});
template.addMember(cloned);
});
subunit.findFirst(ClassOrInterfaceDeclaration.class).get().findAll(FieldDeclaration.class).forEach(fd -> {
FieldDeclaration cloned = fd.clone();
template.addMember(cloned);
});
if (subunit.getPackageDeclaration().isPresent() && !subunit.getPackageDeclaration().get().getNameAsString().equals(clazz.getPackageDeclaration().get().getNameAsString())) {
clazz.addImport(subunit.getPackageDeclaration().get().getNameAsString(), false, true);
}
}
collectSubProcessModels(modelfqcn.substring(modelfqcn.lastIndexOf('.') + 1), template, subprocesses);
enableValidation(template);
securityAnnotated(template);
template.getMembers().sort(new BodyDeclarationComparator());
return clazz;
}
Aggregations