Skip to content

Commit

Permalink
53 scc multiapi converteropenapi rewrite the logic for anyofs (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
jemacineiras authored Oct 3, 2022
1 parent adf1670 commit c05b018
Show file tree
Hide file tree
Showing 16 changed files with 1,525 additions and 465 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ This plugin supports most of the OpenApi/Swagger and AsyncApi, but there are a c
- Using **OpenApi/AsyncApi´s example label** in the parameters/schemas will check in our contracts that the response is equal to the example
value instead of using a Regex.
- **OpenApi**: Since 2.4.0 version, we support the definition of parameters in both Path and Operation object, but you can only define it
in one of them. If you specify them in both objects it will trigger an Exception.
in one of them. ❗❗❗️ We use the Option resolver from OpenApi which will override the Operation parameters if you have a parameter defined in the Path.
- Please be aware that writing an example must be the same type as indicated in the file, otherwise your contract will break.

This is an easy example of a small YAML for OpenApi that will work with our plugin:
Expand Down Expand Up @@ -178,7 +178,6 @@ Currently, this plugin has some limitations that will be addressed in the future
**OpenApi implementation**:
- This plugin allows the use of AllOfs and AnyOfs in the Response section. However, OpenApi does not support AllOfs in this section and AnyOf usage might not work depending on the OpenApi version you are using.
- Some OpenApi functionalities are not implemented yet, such as creating example objects, instead you must use the example tag in every property of the object.
- Due to the OpenApi Parser code, when you use a $ref that points to an external file, there are some limitations when using $ref again in that same file.
Expand Down
20 changes: 13 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>net.coru</groupId>
<artifactId>scc-multiapi-converter</artifactId>
<version>2.7.1</version>
<version>3.0.0</version>
<name>SCC-MultiApi-Converter</name>
<description>Generates Spring Cloud Contracts based on an OpenApi and AsyncApi document</description>
<url>https://github.com/corunet/scc-multiapi-converter</url>
Expand Down Expand Up @@ -120,17 +120,16 @@


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.6.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-verifier</artifactId>
Expand Down Expand Up @@ -190,6 +189,13 @@
<artifactId>spring-cloud-contract-spec-java</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
<scope>test</scope>
</dependency>

</dependencies>
<build>
<pluginManagement>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@
import java.util.Map;
import java.util.Objects;

import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import net.coru.multiapi.converter.utils.BasicTypeConstants;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.cloud.contract.spec.internal.Body;
import org.springframework.cloud.contract.spec.internal.BodyMatchers;
import org.springframework.cloud.contract.spec.internal.MatchingStrategy;
import org.springframework.cloud.contract.spec.internal.MatchingStrategy.Type;
import org.springframework.cloud.contract.spec.internal.QueryParameters;
import org.springframework.cloud.contract.spec.internal.Request;
import org.springframework.cloud.contract.spec.internal.Response;

public final class OpenApiContractConverterUtils {
Expand All @@ -39,53 +42,46 @@ public static String mapRefName(final Schema schema) {
return refName;
}

public static void processBasicResponseTypeBody(final Response response, final Schema schema) {
if (Objects.nonNull(schema.getExample())) {
response.body(schema.getExample());
} else {
switch (schema.getType()) {
case BasicTypeConstants.STRING:
response.body(response.anyAlphaNumeric());
break;
case BasicTypeConstants.INTEGER:
processIntegerFormat(response, schema);
break;
case BasicTypeConstants.NUMBER:
processNumberFormat(response, schema);
break;
case BasicTypeConstants.BOOLEAN:
response.body(response.anyBoolean());
break;
default:
response.body("Error");
break;
}
public static String mapRefName(final Example example) {
String refName = "";
if (Objects.nonNull(example.get$ref())) {
final String[] wholeRef = example.get$ref().split("/");
refName = wholeRef[wholeRef.length - 1];

}
return refName;
}

public static void processBasicRequestTypeBody(final Request request, final Schema schema) {

public static Pair<Body, BodyMatchers> processBasicTypeBody(final Schema schema) {
final Body body;
final BodyMatchers bodyMatchers = new BodyMatchers();
if (Objects.nonNull(schema.getExample())) {
request.body(schema.getExample());
body = new Body(schema.getExample());
} else {
switch (schema.getType()) {
case BasicTypeConstants.STRING:
request.body(request.anyAlphaNumeric());
body = new Body(new Response().anyAlphaNumeric());
bodyMatchers.byRegex(BasicTypeConstants.STRING_REGEX);
break;
case BasicTypeConstants.INTEGER:
processIntegerFormat(request, schema);
body = new Body(processIntegerFormat(schema));
bodyMatchers.byRegex(BasicTypeConstants.INT_REGEX);
break;
case BasicTypeConstants.NUMBER:
processNumberFormat(request, schema);
body = new Body(processNumberFormat(schema));
bodyMatchers.byRegex(BasicTypeConstants.DECIMAL_REGEX);
break;
case BasicTypeConstants.BOOLEAN:
request.body(request.anyBoolean());
body = new Body(new Response().anyBoolean());
bodyMatchers.byRegex(BasicTypeConstants.BOOLEAN_REGEX);
break;
default:
request.body("Error");
body = new Body("Error");
bodyMatchers.byRegex(BasicTypeConstants.DEFAULT_REGEX);
break;
}
}
return Pair.of(body, bodyMatchers);
}

public static void processBasicQueryParameterTypeBody(final QueryParameters queryParameters, final Parameter parameter) {
Expand Down Expand Up @@ -119,8 +115,8 @@ public static void processNumberFormat(final Response response, final Schema sch
response.body(processNumberFormat(schema.getFormat(), schema.getName()));
}

public static void processNumberFormat(final Request request, final Schema schema) {
request.body(processNumberFormat(schema.getFormat(), schema.getName()));
public static Map<String, Object> processNumberFormat(final Schema schema) {
return processNumberFormat(schema.getFormat(), schema.getName());
}

public static void processNumberFormat(final QueryParameters queryParameters, final Parameter parameter) {
Expand All @@ -143,8 +139,8 @@ public static void processIntegerFormat(final Response response, final Schema sc
response.body(processIntegerFormat(schema.getFormat(), schema.getName()));
}

public static void processIntegerFormat(final Request request, final Schema schema) {
request.body(processIntegerFormat(schema.getFormat(), schema.getName()));
public static Map<String, Object> processIntegerFormat(final Schema schema) {
return processIntegerFormat(schema.getFormat(), schema.getName());
}

public static void processIntegerFormat(final QueryParameters queryParameters, final Parameter parameter) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package net.coru.multiapi.converter.openapi.model;

import io.swagger.v3.oas.models.Operation;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.Value;

@Value
@Builder
@RequiredArgsConstructor
public class ConverterPathItem {

OperationType operationType;

Operation operation;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.coru.multiapi.converter.openapi.model;

public enum OperationType {
POST, GET, PATCH, PUT, DELETE;

public static boolean isValid(final String name) {
final boolean result;
switch (name.toUpperCase()) {
case "POST":
case "PUT":
case "GET":
case "PATCH":
case "DELETE":
result = true;
break;
default:
result = false;
break;
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public final class BasicTypeConstants {

public static final String ARRAY = "array";

public static final String MAP = "map";

public static final String ENUM = "enum";

public static final String CHANNELS = "channels";
Expand All @@ -52,10 +54,6 @@ public final class BasicTypeConstants {

public static final String PROPERTIES = "properties";

public static final String SCHEMA = "schema";

public static final String SCHEMAS = "schemas";

public static final String FORMAT = "format";

public static final String EXAMPLE = "example";
Expand All @@ -80,8 +78,7 @@ public final class BasicTypeConstants {

public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory());

public static final Set<String> BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER
);
public static final Set<String> BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER);

private BasicTypeConstants() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,87 +12,87 @@

public class AsyncApiContractConverterTestFixtures {

protected final String EVENT_API_FILE = "src/test/resources/asyncapi/event-api.yml";
protected final static String EVENT_API_FILE = "src/test/resources/asyncapi/event-api.yml";

protected final String TEST_BASIC_TYPES_FILE = "src/test/resources/asyncapi/testBasicTypes.yml";
protected final static String TEST_BASIC_TYPES_FILE = "src/test/resources/asyncapi/testBasicTypes.yml";

protected final String TEST_COMPLEX_OBJECTS_FILE = "src/test/resources/asyncapi/testComplexObjects.yml";
protected final static String TEST_COMPLEX_OBJECTS_FILE = "src/test/resources/asyncapi/testComplexObjects.yml";

protected final String TEST_ARRAYS_FILE = "src/test/resources/asyncapi/testArrays.yml";
protected final static String TEST_ARRAYS_FILE = "src/test/resources/asyncapi/testArrays.yml";

protected final String TEST_ARRAYS_REF_FILE = "src/test/resources/asyncapi/testArraysWithRef.yml";
protected final static String TEST_ARRAYS_REF_FILE = "src/test/resources/asyncapi/testArraysWithRef.yml";

protected final String TEST_ENUMS_FILE = "src/test/resources/asyncapi/testEnums.yml";
protected final static String TEST_ENUMS_FILE = "src/test/resources/asyncapi/testEnums.yml";

protected final String TEST_EXTERNAL_FILE = "src/test/resources/asyncapi/testExternalFiles.yml";
protected final static String TEST_EXTERNAL_FILE = "src/test/resources/asyncapi/testExternalFiles.yml";

protected final String TEST_EXTERNAL_FILE_MULTIPLE_SCHEMAS = "src/test/resources/asyncapi/testExternalFilesWithMultipleSchemas.yml";
protected final static String TEST_EXTERNAL_FILE_MULTIPLE_SCHEMAS = "src/test/resources/asyncapi/testExternalFilesWithMultipleSchemas.yml";

protected final String PUBLISH_NAME = "publishOperation";
protected final static String PUBLISH_NAME = "publishOperation";

protected final String TRIGGERED_BY = "publishOperation()";
protected final static String TRIGGERED_BY = "publishOperation()";

protected final String PUBLISH_SEND_TO = "orderCreated";
protected final static String PUBLISH_SEND_TO = "orderCreated";

protected final String SUBSCRIBE_NAME = "subscribeOperation";
protected final static String SUBSCRIBE_NAME = "subscribeOperation";

protected final String MESSAGE_FROM = "createOrder";
protected final static String MESSAGE_FROM = "createOrder";

protected final String INT_ARRAY_BODY_MATCHER = "order.intArray[0]";
protected final static String INT_ARRAY_BODY_MATCHER = "order.intArray[0]";

protected final String HEADER_NAME = "Accept";
protected final static String HEADER_NAME = "Accept";

protected final String HEADER_VALUE = "application/json";
protected final static String HEADER_VALUE = "application/json";

protected final String ORDER = "order";
protected final static String ORDER = "order";

protected final String ORDERS = "orders";
protected final static String ORDERS = "orders";

protected final String ORDER_LINE = "orderLine";
protected final static String ORDER_LINE = "orderLine";

protected final String EMPLOYEES = "employees";
protected final static String EMPLOYEES = "employees";

protected final String INT_ARRAY = "intArray";
protected final static String INT_ARRAY = "intArray";

protected final String NAME = "name";
protected final static String NAME = "name";

protected final String CORUNET = "Corunet";
protected final static String CORUNET = "Corunet";

protected final String PERSON_NAME = "Carlos";
protected final static String PERSON_NAME = "Carlos";

protected final String ADDRESS = "address";
protected final static String ADDRESS = "address";

protected final String COMPANY_NAME = "companyName";
protected final static String COMPANY_NAME = "companyName";

protected final String REFERENCE_NAME = "referenceName";
protected final static String REFERENCE_NAME = "referenceName";

protected final String STREET = "street";
protected final static String STREET = "street";

protected final String STREET_VALUE = "Calle Sor Joaquina";
protected final static String STREET_VALUE = "Calle Sor Joaquina";

protected final String AMOUNT = "amount";
protected final static String AMOUNT = "amount";

protected final String INTEGER_TYPE = "integerType";
protected final static String INTEGER_TYPE = "integerType";

protected final String INTEGER_TYPE_2 = "integerType2";
protected final static String INTEGER_TYPE_2 = "integerType2";

protected final String FLOAT_TYPE = "floatType";
protected final static String FLOAT_TYPE = "floatType";

protected final String FLOAT_TYPE_2 = "floatType2";
protected final static String FLOAT_TYPE_2 = "floatType2";

protected final String DOUBLE_TYPE = "doubleType";
protected final static String DOUBLE_TYPE = "doubleType";

protected final String STRING_TYPE = "stringType";
protected final static String STRING_TYPE = "stringType";

protected final String BOOLEAN_TYPE = "booleanType";
protected final static String BOOLEAN_TYPE = "booleanType";

protected final String IS_SENT = "isSent";
protected final static String IS_SENT = "isSent";

protected final List<Integer> INT_ARRAY_VALUES = List.of(1, 2, 3);

protected final List<Double> DOUBLE_ARRAY_VALUES = List.of(1.25, 2.5, 3.75);

protected final String[] ENUM_VALUES = {"Corunet", "Sngular"};
final static String[] ENUM_VALUES = {"Corunet", "Sngular"};

protected final Map<String, Object> createOrder() {
Map<String, Object> order = new HashMap<>();
Expand Down
Loading

0 comments on commit c05b018

Please sign in to comment.