Skip to content

Commit

Permalink
feat(element-template-generator): accept json content as parameter in…
Browse files Browse the repository at this point in the history
… template generator (#3180)

* feat(element-template-generator): accept json content as parameter in template generator

* fix(element-template-generator): fix code style

* fix(element-template-generator): fix test
  • Loading branch information
markfarkas-camunda authored Aug 28, 2024
1 parent 9c3d74a commit d6908da
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
*/
package io.camunda.connector.generator.openapi;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.OpenAPIV3Parser;
import java.io.IOException;
import java.util.List;
import java.util.Set;

Expand All @@ -37,7 +39,7 @@ public record OpenApiGenerationSource(
*/
public record Options(boolean rawBody) {}

static final String USAGE = "openapi-outbound [openapi-file] [operation-id]... [--raw-body]";
static final String USAGE = "[operation-id] openapi-outbound [openapi-file]... [--raw-body]";

public OpenApiGenerationSource(List<String> cliParams) {
this(fetchOpenApi(cliParams), extractOperationIds(cliParams), extractOptions(cliParams));
Expand All @@ -48,19 +50,32 @@ private static OpenAPI fetchOpenApi(List<String> cliParams) {
throw new IllegalArgumentException(
"OpenAPI file path or URL must be provided as first parameter");
}
var openApiPath = cliParams.get(0);
var openApiPathOrContent = cliParams.get(0);
var openApiParser = new OpenAPIV3Parser();
try {
return openApiParser.read(openApiPath);
if (isValidJSON(openApiPathOrContent)) {
return openApiParser.readContents(openApiPathOrContent).getOpenAPI();
}
return openApiParser.read(openApiPathOrContent);
} catch (Exception e) {
throw new IllegalArgumentException(
"Failed to parse OpenAPI file from "
+ openApiPath
+ openApiPathOrContent
+ ". Make sure the location is specified correctly and does not require authentication.",
e);
}
}

public static boolean isValidJSON(String jsonInString) {
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(jsonInString);
return true;
} catch (IOException e) {
return false;
}
}

private static Set<String> extractOperationIds(List<String> cliParams) {
var cliParamsWithoutOptions =
cliParams.stream().filter(param -> !param.startsWith("--")).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
package io.camunda.connector.generator.openapi;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.camunda.connector.generator.openapi.OpenApiGenerationSource.Options;
import io.swagger.v3.parser.OpenAPIV3Parser;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;

Expand All @@ -44,6 +48,26 @@ void generate() throws JsonProcessingException {
System.out.println(mapper.writeValueAsString(template));
}

@Test
void generateFromRawJsonContent() throws IOException {
// given
try (var openApiJsonContent =
new FileInputStream("src/test/resources/web-modeler-rest-api.json")) {
String openApiCollectionsJsonContent =
mapper.readValue(openApiJsonContent, JsonNode.class).toString();
var source = new OpenApiGenerationSource(List.of(openApiCollectionsJsonContent));
var generator = new OpenApiOutboundTemplateGenerator();

// when
var templates = generator.generate(source);

// then
System.out.println(mapper.writeValueAsString(templates));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Test
void scan() {
var parser = new OpenAPIV3Parser();
Expand All @@ -52,6 +76,24 @@ void scan() {

var scanResult =
generator.scan(new OpenApiGenerationSource(openApi, Set.of(), new Options(false)));

System.out.println(scanResult);
}

@Test
void scanFromRawJsonContent() {
try (var openApiJsonContent =
new FileInputStream("src/test/resources/web-modeler-rest-api.json")) {
String openApiCollectionsJsonContent =
mapper.readValue(openApiJsonContent, JsonNode.class).toString();
var source = new OpenApiGenerationSource(List.of(openApiCollectionsJsonContent));
var generator = new OpenApiOutboundTemplateGenerator();

var scanResult = generator.scan(source);

System.out.println(scanResult);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

public record PostmanCollectionsGenerationSource(
Expand All @@ -43,35 +44,52 @@ private static PostmanCollectionV210 fetchPostmanCollection(List<String> cliPara
throw new IllegalArgumentException("Incorrect usage");
}

final var collectionPath = cliParams.getFirst();
final var collectionPathOrContent = cliParams.getFirst();

File postmanCollectionsFileJson;
if (collectionPath.startsWith("http")) { // Network
try {
postmanCollectionsFileJson = File.createTempFile("postman-gen", "tmp");
postmanCollectionsFileJson.deleteOnExit();
InputStream collectionUrl = new URL(collectionPath).openStream();
Files.copy(
collectionUrl,
postmanCollectionsFileJson.toPath(),
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else { // Local file system
postmanCollectionsFileJson = new File(collectionPath);
}

if (!postmanCollectionsFileJson.exists() || !postmanCollectionsFileJson.isFile()) {
throw new IllegalArgumentException(
"Incorrect Postman Collections file: " + postmanCollectionsFileJson.getName());
}
JsonNode collectionNode =
Optional.ofNullable(collectionPathOrContent)
.map(
pathOrContent -> {
try {
if (isValidJSON(pathOrContent)) {
try {
return ObjectMapperProvider.getInstance()
.readValue(pathOrContent, JsonNode.class);
} catch (IOException e) {
throw new IllegalArgumentException(
"Couldn't parse Postman Collection to v.2.1.0 standard", e);
}
}
final File postmanCollectionsFileJson;
if (pathOrContent.startsWith("http")) { // Network
postmanCollectionsFileJson = File.createTempFile("postman-gen", "tmp");
postmanCollectionsFileJson.deleteOnExit();
InputStream collectionUrl = new URL(collectionPathOrContent).openStream();
Files.copy(
collectionUrl,
postmanCollectionsFileJson.toPath(),
StandardCopyOption.REPLACE_EXISTING);
} else { // Local file system
postmanCollectionsFileJson = new File(collectionPathOrContent);
}
if (!postmanCollectionsFileJson.exists()
|| !postmanCollectionsFileJson.isFile()) {
throw new IllegalArgumentException(
"Incorrect Postman Collections file: "
+ postmanCollectionsFileJson.getName());
}
return ObjectMapperProvider.getInstance()
.readValue(new FileInputStream(postmanCollectionsFileJson), JsonNode.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
})
.orElseThrow(
() ->
new IllegalArgumentException(
"Postman file path, URL, or content must be provided as first parameter"));

try {
JsonNode collectionNode =
ObjectMapperProvider.getInstance()
.readValue(new FileInputStream(postmanCollectionsFileJson), JsonNode.class);

PostmanCollectionV210 collection;
// When collection shared directly from Postman UI
if (collectionNode.has("collection")) {
Expand All @@ -94,6 +112,15 @@ private static PostmanCollectionV210 fetchPostmanCollection(List<String> cliPara
}
}

public static boolean isValidJSON(String jsonInString) {
try {
ObjectMapperProvider.getInstance().readTree(jsonInString);
return true;
} catch (IOException e) {
return false;
}
}

// 0th element is Postman Collections file; the 1st..Nth - operations
private static Set<String> extractOperationIds(List<String> cliParams) {
if (cliParams.size() == 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package io.camunda.connector.generator.postman;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import io.camunda.connector.generator.api.GeneratorConfiguration;
import io.camunda.connector.generator.api.GeneratorConfiguration.ConnectorMode;
import io.camunda.connector.generator.postman.utils.ObjectMapperProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
Expand Down Expand Up @@ -62,28 +65,40 @@ void scan(List<String> args) {
}

private static Stream<Arguments> commandLineArguments() {
return Stream.of(
// Test case 1: generate all methods
Arguments.of(List.of("src/test/resources/operate-api-saas-bearer.json")),
try (var openApiJsonContent =
new FileInputStream("src/test/resources/operate-api-saas-bearer.json")) {
String postmanCollectionsJsonContent =
ObjectMapperProvider.getInstance()
.readValue(openApiJsonContent, JsonNode.class)
.toString();
return Stream.of(
// Test case 1: generate all methods
Arguments.of(List.of("src/test/resources/operate-api-saas-bearer.json")),

// Test case 2: generate specific methods
Arguments.of(
List.of(
"src/test/resources/postman-books.json",
"/1. Sending requests & inspecting responses/books",
"/1. Sending requests & inspecting responses/book",
"/1. Sending requests & inspecting responses/add book")),
// Test case 2: generate specific methods
Arguments.of(
List.of(
"src/test/resources/postman-books.json",
"/1. Sending requests & inspecting responses/books",
"/1. Sending requests & inspecting responses/book",
"/1. Sending requests & inspecting responses/add book")),

// Test case 3: fetch from internet
Arguments.of(
List.of(
"https://raw.githubusercontent.com/camunda-community-hub/camunda-8-api-postman-collection/main/Operate%20Public%20API%20-%20SaaS.postman_collection.json")),
// Test case 3: fetch from internet
Arguments.of(
List.of(
"https://raw.githubusercontent.com/camunda-community-hub/camunda-8-api-postman-collection/main/Operate%20Public%20API%20-%20SaaS.postman_collection.json")),

// Test case 4: from internet with operations
Arguments.of(
List.of(
"https://raw.githubusercontent.com/camunda-community-hub/camunda-8-api-postman-collection/main/Operate%20Public%20API%20-%20SaaS.postman_collection.json",
"/Process instances/Search for process instances",
"/Process instances/Get process instance by key")));
// Test case 4: from internet with operations
Arguments.of(
List.of(
"https://raw.githubusercontent.com/camunda-community-hub/camunda-8-api-postman-collection/main/Operate%20Public%20API%20-%20SaaS.postman_collection.json",
"/Process instances/Search for process instances",
"/Process instances/Get process instance by key")),

// Test case 5: from raw content
Arguments.of(List.of(postmanCollectionsJsonContent)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

0 comments on commit d6908da

Please sign in to comment.