use of io.automatiko.engine.workflow.process.core.node.FaultNode 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.workflow.process.core.node.FaultNode in project automatiko-engine by automatiko-io.
the class EndEventHandler method handleErrorNode.
@SuppressWarnings("unchecked")
public void handleErrorNode(final Node node, final Element element, final String uri, final String localName, final ExtensibleXmlParser parser) throws SAXException {
FaultNode faultNode = (FaultNode) node;
org.w3c.dom.Node xmlNode = element.getFirstChild();
while (xmlNode != null) {
String nodeName = xmlNode.getNodeName();
if ("dataInputAssociation".equals(nodeName)) {
readFaultDataInputAssociation(xmlNode, faultNode);
} else if ("errorEventDefinition".equals(nodeName)) {
String errorRef = ((Element) xmlNode).getAttribute("errorRef");
if (errorRef != null && errorRef.trim().length() > 0) {
List<Error> errors = (List<Error>) ((ProcessBuildData) parser.getData()).getMetaData("Errors");
if (errors == null) {
throw new IllegalArgumentException("No errors found");
}
Error error = null;
for (Error listError : errors) {
if (errorRef.equals(listError.getId())) {
error = listError;
break;
}
}
if (error == null) {
throw new IllegalArgumentException("Could not find error " + errorRef);
}
faultNode.setFaultName(error.getErrorCode());
faultNode.setTerminateParent(true);
}
}
xmlNode = xmlNode.getNextSibling();
}
}
use of io.automatiko.engine.workflow.process.core.node.FaultNode in project automatiko-engine by automatiko-io.
the class EndEventHandler method handleEscalationNode.
@SuppressWarnings("unchecked")
public void handleEscalationNode(final Node node, final Element element, final String uri, final String localName, final ExtensibleXmlParser parser) throws SAXException {
FaultNode faultNode = (FaultNode) node;
org.w3c.dom.Node xmlNode = element.getFirstChild();
while (xmlNode != null) {
String nodeName = xmlNode.getNodeName();
if ("dataInputAssociation".equals(nodeName)) {
readFaultDataInputAssociation(xmlNode, faultNode);
} else if ("escalationEventDefinition".equals(nodeName)) {
String escalationRef = ((Element) xmlNode).getAttribute("escalationRef");
if (escalationRef != null && escalationRef.trim().length() > 0) {
Map<String, Escalation> escalations = (Map<String, Escalation>) ((ProcessBuildData) parser.getData()).getMetaData(ProcessHandler.ESCALATIONS);
if (escalations == null) {
throw new IllegalArgumentException("No escalations found");
}
Escalation escalation = escalations.get(escalationRef);
if (escalation == null) {
throw new IllegalArgumentException("Could not find escalation " + escalationRef);
}
faultNode.setFaultName(escalation.getEscalationCode());
} else {
// are _required_ to reference a specific escalation(-code).
throw new IllegalArgumentException("End events throwing an escalation must throw *specific* escalations (and not general ones).");
}
}
xmlNode = xmlNode.getNextSibling();
}
}
use of io.automatiko.engine.workflow.process.core.node.FaultNode in project automatiko-engine by automatiko-io.
the class SvgBpmnProcessImageGenerator method buildNodeContainer.
/*
* Build methods
*/
protected void buildNodeContainer(int x, int y, NodeContainer nodeContainer, SVGGraphics2D g2) {
try {
for (Node node : nodeContainer.getNodes()) {
if (node instanceof StartNode) {
buildStartEvent(x, y, (StartNode) node, g2);
} else if (node instanceof EndNode) {
buildEndEvent(x, y, (EndNode) node, g2);
} else if (node instanceof FaultNode) {
buildErrorEndEvent(x, y, (FaultNode) node, g2);
} else if (node instanceof BoundaryEventNode) {
buildBoundaryEvent(x, y, node, g2);
} else if (node instanceof EventNode || node instanceof StateNode) {
buildIntermediateEvent(x, y, node, g2);
} else if (node instanceof HumanTaskNode) {
buildHumanTaskNode(x, y, (HumanTaskNode) node, g2);
} else if (node instanceof ActionNode) {
buildScriptTaskNode(x, y, (ActionNode) node, g2);
} else if (node instanceof WorkItemNode) {
buildServiceTaskNode(x, y, (WorkItemNode) node, g2);
} else if (node instanceof Split || node instanceof Join) {
buildGateway(x, y, node, g2);
} else if (node instanceof ForEachNode) {
buildNodeContainer(x(node), y(node), ((ForEachNode) node).getCompositeNode(), g2);
} else if (node instanceof CompositeNode) {
buildSubprocessNode(x, y, (CompositeNode) node, g2);
int sx = x(node);
int sy = y(node);
buildNodeContainer(sx, sy, (CompositeNode) node, g2);
} else if (node instanceof RuleSetNode) {
buildBusinessRuleTaskNode(x, y, (RuleSetNode) node, g2);
} else if (node instanceof TimerNode) {
buildTimerEvent(x, y, (TimerNode) node, g2);
} else if (node instanceof SubProcessNode) {
buildCallActivity(x, y, (SubProcessNode) node, g2);
}
buildSequenceFlow(x, y, node, g2);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
use of io.automatiko.engine.workflow.process.core.node.FaultNode in project automatiko-engine by automatiko-io.
the class ExecutableProcessFactory method postProcessNodes.
private void postProcessNodes(ExecutableProcess process, NodeContainer container) {
List<String> eventSubProcessHandlers = new ArrayList<String>();
for (Node node : container.getNodes()) {
if (node instanceof NodeContainer) {
// prepare event sub process
if (node instanceof EventSubProcessNode) {
EventSubProcessNode eventSubProcessNode = (EventSubProcessNode) node;
Node[] nodes = eventSubProcessNode.getNodes();
for (Node subNode : nodes) {
// avoids cyclomatic complexity
if (subNode instanceof StartNode) {
processEventSubprocessStartNode(process, ((StartNode) subNode), eventSubProcessNode, eventSubProcessHandlers);
}
}
}
postProcessNodes(process, (NodeContainer) node);
}
}
// process fault node to disable termnate parent if there is event subprocess handler
for (Node node : container.getNodes()) {
if (node instanceof FaultNode) {
FaultNode faultNode = (FaultNode) node;
if (eventSubProcessHandlers.contains(faultNode.getFaultName())) {
faultNode.setTerminateParent(false);
}
}
}
}
Aggregations