use of io.automatiko.engine.codegen.BodyDeclarationComparator in project automatiko-engine by automatiko-io.
the class ProcessesContainerGenerator method classDeclaration.
@Override
public ClassOrInterfaceDeclaration classDeclaration() {
byProcessIdMethodDeclaration.getBody().orElseThrow(() -> new NoSuchElementException("A method declaration doesn't contain a body!")).addStatement(new ReturnStmt(new NullLiteralExpr()));
NodeList<Expression> processIds = NodeList.nodeList(processes.stream().map(p -> new StringLiteralExpr(p.processId())).collect(Collectors.toList()));
processesMethodDeclaration.getBody().orElseThrow(() -> new NoSuchElementException("A method declaration doesn't contain a body!")).addStatement(new ReturnStmt(new MethodCallExpr(new NameExpr(Arrays.class.getCanonicalName()), "asList", processIds)));
FieldDeclaration applicationFieldDeclaration = new FieldDeclaration();
applicationFieldDeclaration.addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, "Application"), "application")).setModifiers(Modifier.Keyword.PRIVATE, Modifier.Keyword.FINAL);
applicationDeclarations.add(applicationFieldDeclaration);
ConstructorDeclaration constructorDeclaration = new ConstructorDeclaration("Processes").addModifier(Modifier.Keyword.PUBLIC).addParameter("Application", "application").setBody(new BlockStmt().addStatement("this.application = application;"));
applicationDeclarations.add(constructorDeclaration);
ClassOrInterfaceDeclaration cls = super.classDeclaration().setMembers(applicationDeclarations);
cls.getMembers().sort(new BodyDeclarationComparator());
return cls;
}
use of io.automatiko.engine.codegen.BodyDeclarationComparator in project automatiko-engine by automatiko-io.
the class MessageConsumerGenerator method generate.
public String generate() {
String sanitizedName = CodegenUtils.triggerSanitizedName(trigger, process.getVersion());
String connector = CodegenUtils.getConnector(INCOMING_PROP_PREFIX + sanitizedName + ".connector", context, (String) trigger.getContext("connector"));
if (connector != null && !OPERATOR_CONNECTOR.equals(connector)) {
context.setApplicationProperty(INCOMING_PROP_PREFIX + sanitizedName + ".connector", connector);
appendConnectorSpecificProperties(connector);
}
// operator consumer only supports starting message endpoints
if (OPERATOR_CONNECTOR.equals(connector) && !trigger.isStart()) {
return null;
}
CompilationUnit clazz = parse(this.getClass().getResourceAsStream(consumerTemplate(connector)));
clazz.setPackageDeclaration(process.getPackageName());
clazz.addImport(modelfqcn);
// add functions so they can be easily accessed in message consumer classes
clazz.addImport(new ImportDeclaration(BaseFunctions.class.getCanonicalName(), true, true));
context.getBuildContext().classThatImplement(Functions.class.getCanonicalName()).forEach(c -> clazz.addImport(new ImportDeclaration(c, true, true)));
ClassOrInterfaceDeclaration template = clazz.findFirst(ClassOrInterfaceDeclaration.class).get();
template.setName(resourceClazzName);
template.findAll(ClassOrInterfaceType.class).forEach(cls -> interpolateTypes(cls, dataClazzName));
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("configure")).forEach(md -> md.addAnnotation("javax.annotation.PostConstruct"));
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("consume") || md.getNameAsString().equals("cleanup") || md.getNameAsString().equals("reconcile")).forEach(md -> {
md.findAll(StringLiteralExpr.class).forEach(str -> str.setString(str.asString().replace("$Trigger$", trigger.getName())));
md.findAll(ClassOrInterfaceType.class).forEach(t -> t.setName(t.getNameAsString().replace("$DataEventType$", messageDataEventClassName)));
md.findAll(ClassOrInterfaceType.class).forEach(t -> t.setName(t.getNameAsString().replace("$DataType$", trigger.getDataType())));
md.setType(md.getTypeAsString().replace("$DataType$", trigger.getDataType()));
});
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("convert")).forEach(md -> {
md.setType(md.getTypeAsString().replace("$DataType$", trigger.getDataType()));
md.findAll(CastExpr.class).forEach(c -> c.setType(c.getTypeAsString().replace("$DataType$", trigger.getDataType())));
md.findAll(ClassOrInterfaceType.class).forEach(t -> t.setName(t.getNameAsString().replace("$DataType$", trigger.getDataType())));
});
if (trigger.getModelRef().startsWith("#")) {
template.findAll(MethodCallExpr.class).stream().filter(m -> m.getNameAsString().endsWith("$ModelRef$")).forEach(m -> {
m.getParentNode().ifPresent(p -> p.removeForced());
});
} else {
template.findAll(MethodCallExpr.class).forEach(this::interpolateStrings);
}
if (useInjection()) {
if (!OPERATOR_CONNECTOR.equals(connector)) {
annotator.withApplicationComponent(template);
}
template.findAll(FieldDeclaration.class, fd -> isProcessField(fd)).forEach(fd -> annotator.withNamedInjection(fd, processId + version));
template.findAll(FieldDeclaration.class, fd -> isApplicationField(fd)).forEach(fd -> annotator.withInjection(fd));
template.findAll(FieldDeclaration.class, fd -> fd.getVariables().get(0).getNameAsString().equals("converter")).forEach(fd -> {
annotator.withInjection(fd);
fd.getVariable(0).setType(fd.getVariable(0).getTypeAsString().replace("$DataType$", trigger.getDataType()));
});
template.findAll(FieldDeclaration.class, fd -> fd.getVariable(0).getNameAsString().equals("useCloudEvents")).forEach(fd -> annotator.withConfigInjection(fd, "quarkus.automatiko.messaging.as-cloudevents"));
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("consume")).forEach(md -> {
if (persistence) {
annotator.withBlocking(md);
}
annotator.withIncomingMessage(md, sanitizedName);
if (context.getBuildContext().hasClassAvailable("org.eclipse.microprofile.opentracing.Traced")) {
md.addAnnotation("org.eclipse.microprofile.opentracing.Traced");
}
});
} else {
template.findAll(FieldDeclaration.class, fd -> isProcessField(fd)).forEach(fd -> initializeProcessField(fd, template));
template.findAll(FieldDeclaration.class, fd -> isApplicationField(fd)).forEach(fd -> initializeApplicationField(fd, template));
template.findAll(FieldDeclaration.class, fd -> fd.getVariables().get(0).getNameAsString().equals("converter")).forEach(fd -> {
fd.getVariable(0).setType(fd.getVariable(0).getTypeAsString().replace("$DataType$", trigger.getDataType()));
});
}
BlockStmt filterExpressionBody = new BlockStmt();
if (trigger.getContext("filterExpression") != null) {
filterExpressionBody.addStatement(new ReturnStmt(new NameExpr((String) trigger.getContext("filterExpression"))));
} else {
filterExpressionBody.addStatement(new ReturnStmt(new BooleanLiteralExpr(true)));
}
BlockStmt body = new BlockStmt();
if (trigger.getCorrelation() != null) {
body.addStatement(new ReturnStmt(new StringLiteralExpr(trigger.getCorrelation())));
} else if (trigger.getCorrelationExpression() != null) {
body.addStatement(new ReturnStmt(new NameExpr(trigger.getCorrelationExpression())));
} else {
body.addStatement(new ReturnStmt(new NullLiteralExpr()));
}
boolean cloudEvents = context.getBuildContext().config().messaging().asCloudevents() || Boolean.parseBoolean(context.getApplicationProperty("quarkus.automatiko.messaging.as-cloudevents").orElse("false"));
if (cloudEvents) {
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("correlationEvent")).forEach(md -> {
md.setBody(body);
md.getParameters().get(0).setType(messageDataEventClassName);
});
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("acceptedEvent")).forEach(md -> {
md.setBody(filterExpressionBody);
md.getParameters().get(0).setType(messageDataEventClassName);
});
} else {
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("correlationPayload")).forEach(md -> {
md.setBody(body);
md.getParameters().get(0).setType(trigger.getDataType());
});
template.findAll(MethodDeclaration.class).stream().filter(md -> md.getNameAsString().equals("acceptedPayload")).forEach(md -> {
md.setBody(filterExpressionBody);
md.getParameters().get(0).setType(trigger.getDataType());
});
}
template.addMember(new MethodDeclaration().setName("canStartInstance").setType(Boolean.class).setModifiers(Keyword.PROTECTED).setBody(new BlockStmt().addStatement(new ReturnStmt(new BooleanLiteralExpr(trigger.isStart())))));
// add connector and message name as static fields of the class
FieldDeclaration connectorField = new FieldDeclaration().setStatic(true).setFinal(true).addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, "String"), "CONNECTOR", new StringLiteralExpr(connector)));
template.addMember(connectorField);
FieldDeclaration messageNameField = new FieldDeclaration().setStatic(true).setFinal(true).addVariable(new VariableDeclarator(new ClassOrInterfaceType(null, "String"), "MESSAGE", new StringLiteralExpr(trigger.getName())));
template.addMember(messageNameField);
if (OPERATOR_CONNECTOR.equals(connector)) {
// add event filter
String eventFilterClass = (String) trigger.getContext("eventFilter");
if (eventFilterClass != null && !eventFilterClass.isEmpty()) {
AnnotationExpr controllerAnnotation = template.getAnnotationByName("Controller").get();
((NormalAnnotationExpr) controllerAnnotation).addPair("eventFilters", new NameExpr(eventFilterClass + ".class"));
}
}
template.getMembers().sort(new BodyDeclarationComparator());
ImportsOrganizer.organize(clazz);
return clazz.toString().replaceAll("\\$DataType\\$", trigger.getDataType()).replaceAll("\\$DataEventType\\$", messageDataEventClassName).replaceAll("\\$ProcessId\\$", processId + version).replaceAll("\\$GenControllerParam\\$", (String) trigger.getContext("generationAware", "true")).replaceAll("\\$ControllerParam\\$", "{" + Stream.of(namespaces.split(",")).filter(s -> !s.trim().isEmpty()).map(s -> "\"" + s.trim() + "\"").collect(Collectors.joining(",")) + "}");
}
use of io.automatiko.engine.codegen.BodyDeclarationComparator 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;
}
use of io.automatiko.engine.codegen.BodyDeclarationComparator in project automatiko-engine by automatiko-io.
the class PersistenceGenerator method dbBasedPersistence.
protected void dbBasedPersistence(List<GeneratedFile> generatedFiles) {
ClassOrInterfaceDeclaration persistenceProviderClazz = new ClassOrInterfaceDeclaration().setName("ProcessInstancesFactoryImpl").setModifiers(Modifier.Keyword.PUBLIC).addExtendedType("io.automatiko.engine.addons.persistence.AbstractProcessInstancesFactory");
CompilationUnit compilationUnit = new CompilationUnit("io.automatiko.engine.addons.persistence.impl");
compilationUnit.getTypes().add(persistenceProviderClazz);
if (useInjection()) {
annotator.withApplicationComponent(persistenceProviderClazz);
addCodecComponents(persistenceProviderClazz);
}
String packageName = compilationUnit.getPackageDeclaration().map(pd -> pd.getName().toString()).orElse("");
String clazzName = packageName + "." + persistenceProviderClazz.findFirst(ClassOrInterfaceDeclaration.class).map(c -> c.getName().toString()).get();
generatedFiles.add(new GeneratedFile(GeneratedFile.Type.CLASS, clazzName.replace('.', '/') + ".java", compilationUnit.toString().getBytes(StandardCharsets.UTF_8)));
persistenceProviderClazz.getMembers().sort(new BodyDeclarationComparator());
}
Aggregations