Skip to content

Commit c05b018

Browse files
authored
53 scc multiapi converteropenapi rewrite the logic for anyofs (#70)
1 parent adf1670 commit c05b018

16 files changed

+1525
-465
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ This plugin supports most of the OpenApi/Swagger and AsyncApi, but there are a c
6161
- Using **OpenApi/AsyncApi´s example label** in the parameters/schemas will check in our contracts that the response is equal to the example
6262
value instead of using a Regex.
6363
- **OpenApi**: Since 2.4.0 version, we support the definition of parameters in both Path and Operation object, but you can only define it
64-
in one of them. If you specify them in both objects it will trigger an Exception.
64+
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.
6565
- Please be aware that writing an example must be the same type as indicated in the file, otherwise your contract will break.
6666

6767
This is an easy example of a small YAML for OpenApi that will work with our plugin:
@@ -178,7 +178,6 @@ Currently, this plugin has some limitations that will be addressed in the future
178178
179179
**OpenApi implementation**:
180180
181-
- 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.
182181
- 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.
183182
- 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.
184183

pom.xml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

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

121121

122122
<dependencies>
123-
<dependency>
124-
<groupId>org.springframework.boot</groupId>
125-
<artifactId>spring-boot-starter-test</artifactId>
126-
<version>2.6.7</version>
127-
<scope>test</scope>
128-
</dependency>
129123
<dependency>
130124
<groupId>org.apache.commons</groupId>
131125
<artifactId>commons-lang3</artifactId>
132126
<version>3.12.0</version>
133127
</dependency>
128+
<dependency>
129+
<groupId>org.apache.commons</groupId>
130+
<artifactId>commons-collections4</artifactId>
131+
<version>4.4</version>
132+
</dependency>
134133
<dependency>
135134
<groupId>org.springframework.cloud</groupId>
136135
<artifactId>spring-cloud-contract-verifier</artifactId>
@@ -190,6 +189,13 @@
190189
<artifactId>spring-cloud-contract-spec-java</artifactId>
191190
<version>3.1.3</version>
192191
</dependency>
192+
<dependency>
193+
<groupId>org.assertj</groupId>
194+
<artifactId>assertj-core</artifactId>
195+
<version>3.23.1</version>
196+
<scope>test</scope>
197+
</dependency>
198+
193199
</dependencies>
194200
<build>
195201
<pluginManagement>

src/main/java/net/coru/multiapi/converter/openapi/OpenApiContractConverter.java

Lines changed: 721 additions & 224 deletions
Large diffs are not rendered by default.

src/main/java/net/coru/multiapi/converter/openapi/OpenApiContractConverterUtils.java

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
1010
import java.util.Map;
1111
import java.util.Objects;
1212

13+
import io.swagger.v3.oas.models.examples.Example;
1314
import io.swagger.v3.oas.models.media.ArraySchema;
1415
import io.swagger.v3.oas.models.media.Schema;
1516
import io.swagger.v3.oas.models.parameters.Parameter;
1617
import net.coru.multiapi.converter.utils.BasicTypeConstants;
18+
import org.apache.commons.lang3.tuple.Pair;
19+
import org.springframework.cloud.contract.spec.internal.Body;
20+
import org.springframework.cloud.contract.spec.internal.BodyMatchers;
1721
import org.springframework.cloud.contract.spec.internal.MatchingStrategy;
1822
import org.springframework.cloud.contract.spec.internal.MatchingStrategy.Type;
1923
import org.springframework.cloud.contract.spec.internal.QueryParameters;
20-
import org.springframework.cloud.contract.spec.internal.Request;
2124
import org.springframework.cloud.contract.spec.internal.Response;
2225

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

42-
public static void processBasicResponseTypeBody(final Response response, final Schema schema) {
43-
if (Objects.nonNull(schema.getExample())) {
44-
response.body(schema.getExample());
45-
} else {
46-
switch (schema.getType()) {
47-
case BasicTypeConstants.STRING:
48-
response.body(response.anyAlphaNumeric());
49-
break;
50-
case BasicTypeConstants.INTEGER:
51-
processIntegerFormat(response, schema);
52-
break;
53-
case BasicTypeConstants.NUMBER:
54-
processNumberFormat(response, schema);
55-
break;
56-
case BasicTypeConstants.BOOLEAN:
57-
response.body(response.anyBoolean());
58-
break;
59-
default:
60-
response.body("Error");
61-
break;
62-
}
45+
public static String mapRefName(final Example example) {
46+
String refName = "";
47+
if (Objects.nonNull(example.get$ref())) {
48+
final String[] wholeRef = example.get$ref().split("/");
49+
refName = wholeRef[wholeRef.length - 1];
50+
6351
}
52+
return refName;
6453
}
6554

66-
public static void processBasicRequestTypeBody(final Request request, final Schema schema) {
67-
55+
public static Pair<Body, BodyMatchers> processBasicTypeBody(final Schema schema) {
56+
final Body body;
57+
final BodyMatchers bodyMatchers = new BodyMatchers();
6858
if (Objects.nonNull(schema.getExample())) {
69-
request.body(schema.getExample());
59+
body = new Body(schema.getExample());
7060
} else {
7161
switch (schema.getType()) {
7262
case BasicTypeConstants.STRING:
73-
request.body(request.anyAlphaNumeric());
63+
body = new Body(new Response().anyAlphaNumeric());
64+
bodyMatchers.byRegex(BasicTypeConstants.STRING_REGEX);
7465
break;
7566
case BasicTypeConstants.INTEGER:
76-
processIntegerFormat(request, schema);
67+
body = new Body(processIntegerFormat(schema));
68+
bodyMatchers.byRegex(BasicTypeConstants.INT_REGEX);
7769
break;
7870
case BasicTypeConstants.NUMBER:
79-
processNumberFormat(request, schema);
71+
body = new Body(processNumberFormat(schema));
72+
bodyMatchers.byRegex(BasicTypeConstants.DECIMAL_REGEX);
8073
break;
8174
case BasicTypeConstants.BOOLEAN:
82-
request.body(request.anyBoolean());
75+
body = new Body(new Response().anyBoolean());
76+
bodyMatchers.byRegex(BasicTypeConstants.BOOLEAN_REGEX);
8377
break;
8478
default:
85-
request.body("Error");
79+
body = new Body("Error");
80+
bodyMatchers.byRegex(BasicTypeConstants.DEFAULT_REGEX);
8681
break;
8782
}
8883
}
84+
return Pair.of(body, bodyMatchers);
8985
}
9086

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

122-
public static void processNumberFormat(final Request request, final Schema schema) {
123-
request.body(processNumberFormat(schema.getFormat(), schema.getName()));
118+
public static Map<String, Object> processNumberFormat(final Schema schema) {
119+
return processNumberFormat(schema.getFormat(), schema.getName());
124120
}
125121

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

146-
public static void processIntegerFormat(final Request request, final Schema schema) {
147-
request.body(processIntegerFormat(schema.getFormat(), schema.getName()));
142+
public static Map<String, Object> processIntegerFormat(final Schema schema) {
143+
return processIntegerFormat(schema.getFormat(), schema.getName());
148144
}
149145

150146
public static void processIntegerFormat(final QueryParameters queryParameters, final Parameter parameter) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package net.coru.multiapi.converter.openapi.model;
2+
3+
import io.swagger.v3.oas.models.Operation;
4+
import lombok.Builder;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.Value;
7+
8+
@Value
9+
@Builder
10+
@RequiredArgsConstructor
11+
public class ConverterPathItem {
12+
13+
OperationType operationType;
14+
15+
Operation operation;
16+
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package net.coru.multiapi.converter.openapi.model;
2+
3+
public enum OperationType {
4+
POST, GET, PATCH, PUT, DELETE;
5+
6+
public static boolean isValid(final String name) {
7+
final boolean result;
8+
switch (name.toUpperCase()) {
9+
case "POST":
10+
case "PUT":
11+
case "GET":
12+
case "PATCH":
13+
case "DELETE":
14+
result = true;
15+
break;
16+
default:
17+
result = false;
18+
break;
19+
}
20+
return result;
21+
}
22+
}

src/main/java/net/coru/multiapi/converter/utils/BasicTypeConstants.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public final class BasicTypeConstants {
4040

4141
public static final String ARRAY = "array";
4242

43+
public static final String MAP = "map";
44+
4345
public static final String ENUM = "enum";
4446

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

5355
public static final String PROPERTIES = "properties";
5456

55-
public static final String SCHEMA = "schema";
56-
57-
public static final String SCHEMAS = "schemas";
58-
5957
public static final String FORMAT = "format";
6058

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

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

83-
public static final Set<String> BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER
84-
);
81+
public static final Set<String> BASIC_OBJECT_TYPE = Set.of(NUMBER, STRING, BOOLEAN, INTEGER);
8582

8683
private BasicTypeConstants() {
8784

src/test/java/net/coru/multiapi/converter/asyncapi/AsyncApiContractConverterTestFixtures.java

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,87 +12,87 @@
1212

1313
public class AsyncApiContractConverterTestFixtures {
1414

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

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

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

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

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

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

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

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

31-
protected final String PUBLISH_NAME = "publishOperation";
31+
protected final static String PUBLISH_NAME = "publishOperation";
3232

33-
protected final String TRIGGERED_BY = "publishOperation()";
33+
protected final static String TRIGGERED_BY = "publishOperation()";
3434

35-
protected final String PUBLISH_SEND_TO = "orderCreated";
35+
protected final static String PUBLISH_SEND_TO = "orderCreated";
3636

37-
protected final String SUBSCRIBE_NAME = "subscribeOperation";
37+
protected final static String SUBSCRIBE_NAME = "subscribeOperation";
3838

39-
protected final String MESSAGE_FROM = "createOrder";
39+
protected final static String MESSAGE_FROM = "createOrder";
4040

41-
protected final String INT_ARRAY_BODY_MATCHER = "order.intArray[0]";
41+
protected final static String INT_ARRAY_BODY_MATCHER = "order.intArray[0]";
4242

43-
protected final String HEADER_NAME = "Accept";
43+
protected final static String HEADER_NAME = "Accept";
4444

45-
protected final String HEADER_VALUE = "application/json";
45+
protected final static String HEADER_VALUE = "application/json";
4646

47-
protected final String ORDER = "order";
47+
protected final static String ORDER = "order";
4848

49-
protected final String ORDERS = "orders";
49+
protected final static String ORDERS = "orders";
5050

51-
protected final String ORDER_LINE = "orderLine";
51+
protected final static String ORDER_LINE = "orderLine";
5252

53-
protected final String EMPLOYEES = "employees";
53+
protected final static String EMPLOYEES = "employees";
5454

55-
protected final String INT_ARRAY = "intArray";
55+
protected final static String INT_ARRAY = "intArray";
5656

57-
protected final String NAME = "name";
57+
protected final static String NAME = "name";
5858

59-
protected final String CORUNET = "Corunet";
59+
protected final static String CORUNET = "Corunet";
6060

61-
protected final String PERSON_NAME = "Carlos";
61+
protected final static String PERSON_NAME = "Carlos";
6262

63-
protected final String ADDRESS = "address";
63+
protected final static String ADDRESS = "address";
6464

65-
protected final String COMPANY_NAME = "companyName";
65+
protected final static String COMPANY_NAME = "companyName";
6666

67-
protected final String REFERENCE_NAME = "referenceName";
67+
protected final static String REFERENCE_NAME = "referenceName";
6868

69-
protected final String STREET = "street";
69+
protected final static String STREET = "street";
7070

71-
protected final String STREET_VALUE = "Calle Sor Joaquina";
71+
protected final static String STREET_VALUE = "Calle Sor Joaquina";
7272

73-
protected final String AMOUNT = "amount";
73+
protected final static String AMOUNT = "amount";
7474

75-
protected final String INTEGER_TYPE = "integerType";
75+
protected final static String INTEGER_TYPE = "integerType";
7676

77-
protected final String INTEGER_TYPE_2 = "integerType2";
77+
protected final static String INTEGER_TYPE_2 = "integerType2";
7878

79-
protected final String FLOAT_TYPE = "floatType";
79+
protected final static String FLOAT_TYPE = "floatType";
8080

81-
protected final String FLOAT_TYPE_2 = "floatType2";
81+
protected final static String FLOAT_TYPE_2 = "floatType2";
8282

83-
protected final String DOUBLE_TYPE = "doubleType";
83+
protected final static String DOUBLE_TYPE = "doubleType";
8484

85-
protected final String STRING_TYPE = "stringType";
85+
protected final static String STRING_TYPE = "stringType";
8686

87-
protected final String BOOLEAN_TYPE = "booleanType";
87+
protected final static String BOOLEAN_TYPE = "booleanType";
8888

89-
protected final String IS_SENT = "isSent";
89+
protected final static String IS_SENT = "isSent";
9090

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

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

95-
protected final String[] ENUM_VALUES = {"Corunet", "Sngular"};
95+
final static String[] ENUM_VALUES = {"Corunet", "Sngular"};
9696

9797
protected final Map<String, Object> createOrder() {
9898
Map<String, Object> order = new HashMap<>();

0 commit comments

Comments
 (0)