|
15 | 15 | */
|
16 | 16 | package io.serverlessworkflow.impl.executors;
|
17 | 17 |
|
| 18 | +import com.fasterxml.jackson.core.type.TypeReference; |
18 | 19 | import com.fasterxml.jackson.databind.JsonNode;
|
19 | 20 | import io.serverlessworkflow.api.types.CallOpenAPI;
|
| 21 | +import io.serverlessworkflow.api.types.Endpoint; |
| 22 | +import io.serverlessworkflow.api.types.EndpointUri; |
| 23 | +import io.serverlessworkflow.api.types.OpenAPIArguments; |
20 | 24 | import io.serverlessworkflow.api.types.TaskBase;
|
| 25 | +import io.serverlessworkflow.api.types.UriTemplate; |
21 | 26 | import io.serverlessworkflow.impl.TaskContext;
|
22 | 27 | import io.serverlessworkflow.impl.WorkflowContext;
|
23 | 28 | import io.serverlessworkflow.impl.WorkflowDefinition;
|
| 29 | +import io.serverlessworkflow.impl.WorkflowUtils; |
| 30 | +import io.serverlessworkflow.impl.expressions.Expression; |
| 31 | +import io.serverlessworkflow.impl.expressions.ExpressionFactory; |
| 32 | +import io.serverlessworkflow.impl.json.JsonUtils; |
| 33 | +import jakarta.ws.rs.client.Client; |
| 34 | +import jakarta.ws.rs.client.ClientBuilder; |
| 35 | +import jakarta.ws.rs.client.WebTarget; |
| 36 | + |
| 37 | +import java.util.Map; |
| 38 | +import java.util.Optional; |
24 | 39 |
|
25 | 40 | public class OpenAPIExecutor implements CallableTask<CallOpenAPI> {
|
| 41 | + private static final Client client = ClientBuilder.newClient(); |
| 42 | + private TargetSupplier targetSupplier; |
| 43 | + |
| 44 | + @FunctionalInterface |
| 45 | + private interface TargetSupplier { |
| 46 | + WebTarget apply(WorkflowContext workflow, TaskContext<?> task, JsonNode node); |
| 47 | + } |
| 48 | + |
| 49 | + @Override |
| 50 | + public void init(CallOpenAPI task, WorkflowDefinition definition) { |
| 51 | + OpenAPIArguments args = task.getWith(); |
| 52 | + this.targetSupplier = getTargetSupplier(args.getDocument().getEndpoint(), definition.expressionFactory(), args.getOperationId()); |
| 53 | + } |
| 54 | + |
| 55 | + @Override |
| 56 | + public JsonNode apply( |
| 57 | + WorkflowContext workflowContext, TaskContext<CallOpenAPI> taskContext, JsonNode input) { |
| 58 | + |
| 59 | + WebTarget target = this.targetSupplier.apply(workflowContext, taskContext, input); |
| 60 | + |
| 61 | + |
| 62 | + return input; |
| 63 | + } |
| 64 | + |
| 65 | + @Override |
| 66 | + public boolean accept(Class<? extends TaskBase> clazz) { |
| 67 | + return clazz.isAssignableFrom(CallOpenAPI.class); |
| 68 | + } |
| 69 | + |
| 70 | + private static TargetSupplier getURISupplier(UriTemplate template, String operationId) { |
| 71 | + if (template.getLiteralUri() != null) { |
| 72 | + |
| 73 | + Optional<JsonNode> jsonNode = WorkflowUtils.classpathResourceToNode(template.getLiteralUri().toString()); |
| 74 | + |
| 75 | + if (jsonNode.isEmpty()) { |
| 76 | + throw new IllegalArgumentException("Invalid OpenAPI specification " + template.getLiteralUri().toString()); |
| 77 | + } |
| 78 | + |
| 79 | + String host = OpenAPIReader.getHost(jsonNode.get()); |
| 80 | + |
| 81 | + JsonNode operation = OpenAPIReader.readOperation(jsonNode.get(), operationId); |
| 82 | + |
| 83 | + if (operation == null) { |
| 84 | + throw new IllegalArgumentException("Invalid OpenAPI specification. There is no operation ID " + operationId); |
| 85 | + } |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | + return (w, t, n) -> client.target(host); |
| 90 | + } else if (template.getLiteralUriTemplate() != null) { |
| 91 | + return (w, t, n) -> |
| 92 | + client |
| 93 | + .target(template.getLiteralUriTemplate()) |
| 94 | + .resolveTemplates( |
| 95 | + JsonUtils.mapper().convertValue(n, new TypeReference<Map<String, Object>>() { |
| 96 | + })); |
| 97 | + } |
| 98 | + throw new IllegalArgumentException("Invalid uritemplate definition " + template); |
| 99 | + } |
| 100 | + |
| 101 | + private static class ExpressionURISupplier implements TargetSupplier { |
| 102 | + private Expression expr; |
26 | 103 |
|
27 |
| - @Override |
28 |
| - public void init(CallOpenAPI task, WorkflowDefinition definition) {} |
| 104 | + public ExpressionURISupplier(Expression expr) { |
| 105 | + this.expr = expr; |
| 106 | + } |
29 | 107 |
|
30 |
| - @Override |
31 |
| - public JsonNode apply( |
32 |
| - WorkflowContext workflowContext, TaskContext<CallOpenAPI> taskContext, JsonNode input) { |
33 |
| - return input; |
34 |
| - } |
| 108 | + @Override |
| 109 | + public WebTarget apply(WorkflowContext workflow, TaskContext<?> task, JsonNode node) { |
| 110 | + return client.target(expr.eval(workflow, Optional.of(task), node).asText()); |
| 111 | + } |
| 112 | + } |
35 | 113 |
|
36 |
| - @Override |
37 |
| - public boolean accept(Class<? extends TaskBase> clazz) { |
38 |
| - return clazz.isAssignableFrom(CallOpenAPI.class); |
39 |
| - } |
| 114 | + private static TargetSupplier getTargetSupplier( |
| 115 | + Endpoint endpoint, ExpressionFactory expressionFactory, String operationId) { |
| 116 | + if (endpoint.getEndpointConfiguration() != null) { |
| 117 | + EndpointUri uri = endpoint.getEndpointConfiguration().getUri(); |
| 118 | + if (uri.getLiteralEndpointURI() != null) { |
| 119 | + return getURISupplier(uri.getLiteralEndpointURI(), operationId); |
| 120 | + } else if (uri.getExpressionEndpointURI() != null) { |
| 121 | + return new ExpressionURISupplier( |
| 122 | + expressionFactory.getExpression(uri.getExpressionEndpointURI())); |
| 123 | + } |
| 124 | + } else if (endpoint.getRuntimeExpression() != null) { |
| 125 | + return new ExpressionURISupplier( |
| 126 | + expressionFactory.getExpression(endpoint.getRuntimeExpression())); |
| 127 | + } else if (endpoint.getUriTemplate() != null) { |
| 128 | + return getURISupplier(endpoint.getUriTemplate(), operationId); |
| 129 | + } |
| 130 | + throw new IllegalArgumentException("Invalid endpoint definition " + endpoint); |
| 131 | + } |
40 | 132 | }
|
0 commit comments