Skip to content

Commit 9a787c5

Browse files
authored
Merge pull request #44 from quen2404/vendor-extensions
Vendor extensions support
2 parents a4709d4 + 6e156b6 commit 9a787c5

15 files changed

+152
-16
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ try {
129129
}
130130
```
131131

132+
### Extensions
133+
This project uses Java Service Provider Inteface (SPI) so additional extensions can be added.
134+
135+
To build your own extension, you simply need to create a `src/main/resources/META-INF/services/com.qdesrame.openapi.diff.compare.ExtensionDiff` file with the full classname of your implementation. Your class must also implement the `com.qdesrame.openapi.diff.compare.ExtensionDiff` interface. Then, including your library with the `openapi-diff` module will cause it to be triggered automatically.
136+
132137
# Example
133138
### CLI Output
134139

src/main/java/com/qdesrame/openapi/diff/compare/ContentDiff.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public Optional<ChangedContent> diff(Content left, Content right, DiffContext co
3636
MediaType oldMediaType = left.get(mediaTypeKey);
3737
MediaType newMediaType = right.get(mediaTypeKey);
3838
ChangedMediaType changedMediaType = new ChangedMediaType(oldMediaType.getSchema(), newMediaType.getSchema(), context);
39-
openApiDiff.getSchemaDiff().diff(new HashSet<>(), oldMediaType.getSchema(), newMediaType.getSchema(), context).ifPresent(changedMediaType::setChangedSchema);
39+
openApiDiff.getSchemaDiff().diff(new HashSet<>(), oldMediaType.getSchema(), newMediaType.getSchema(), context.copyWithRequired(true)).ifPresent(changedMediaType::setChangedSchema);
4040
if (!isUnchanged(changedMediaType)) {
4141
changedMediaTypes.put(mediaTypeKey, changedMediaType);
4242
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.qdesrame.openapi.diff.compare;
2+
3+
import com.qdesrame.openapi.diff.model.Changed;
4+
import com.qdesrame.openapi.diff.model.DiffContext;
5+
6+
import java.util.Optional;
7+
8+
public interface ExtensionDiff {
9+
10+
ExtensionDiff setOpenApiDiff(OpenApiDiff openApiDiff);
11+
12+
String getName();
13+
14+
Optional<Changed> diff(Object left, Object right, DiffContext context);
15+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.qdesrame.openapi.diff.compare;
2+
3+
import com.qdesrame.openapi.diff.model.DiffContext;
4+
import com.qdesrame.openapi.diff.model.schema.ChangedExtensions;
5+
6+
import java.util.*;
7+
8+
import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
9+
10+
public class ExtensionsDiff {
11+
private final OpenApiDiff openApiDiff;
12+
13+
private ServiceLoader<ExtensionDiff> extensionsLoader = ServiceLoader.load(ExtensionDiff.class);
14+
private List<ExtensionDiff> extensionsDiff = new ArrayList<>();
15+
16+
public ExtensionsDiff(OpenApiDiff openApiDiff) {
17+
this.openApiDiff = openApiDiff;
18+
this.extensionsLoader.reload();
19+
for (ExtensionDiff anExtensionsLoader : this.extensionsLoader) {
20+
extensionsDiff.add(anExtensionsLoader);
21+
}
22+
}
23+
24+
public Optional<ChangedExtensions> diff(Map<String, Object> left, Map<String, Object> right, DiffContext context) {
25+
if (null == left) left = new HashMap<>();
26+
if (null == right) right = new HashMap<>();
27+
ChangedExtensions changedExtensions = new ChangedExtensions(left, new HashMap<>(right), context);
28+
changedExtensions.getIncreased().putAll(right);
29+
for (String key : left.keySet()) {
30+
if (changedExtensions.getIncreased().containsKey(key)) {
31+
Optional<ExtensionDiff> extensionDiff = extensionsDiff.stream()
32+
.filter(diff -> ("x-" + diff.getName()).equals(key)).findFirst();
33+
Object leftValue = left.get(key);
34+
Object rightValue = changedExtensions.getIncreased().remove(key);
35+
extensionDiff.ifPresent(diff -> diff.setOpenApiDiff(openApiDiff).diff(leftValue, rightValue, context)
36+
.ifPresent(changed -> changedExtensions.getChanged().put(key, changed)));
37+
} else {
38+
changedExtensions.getMissing().put(key, left.get(key));
39+
}
40+
}
41+
return isChanged(changedExtensions);
42+
}
43+
}

src/main/java/com/qdesrame/openapi/diff/compare/HeaderDiff.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ protected Optional<ChangedHeader> computeDiff(HashSet<String> refSet, Header lef
4444
changedHeader.setChangeDeprecated(!Boolean.TRUE.equals(left.getDeprecated()) && Boolean.TRUE.equals(right.getDeprecated()));
4545
changedHeader.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle()));
4646
changedHeader.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
47-
openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema(), context).ifPresent(changedHeader::setChangedSchema);
47+
openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema(), context.copyWithRequired(true)).ifPresent(changedHeader::setChangedSchema);
4848
openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context).ifPresent(changedHeader::setChangedContent);
4949

5050
return isChanged(changedHeader);

src/main/java/com/qdesrame/openapi/diff/compare/OpenApiDiff.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class OpenApiDiff {
4040
private SecuritySchemeDiff securitySchemeDiff;
4141
private OAuthFlowsDiff oAuthFlowsDiff;
4242
private OAuthFlowDiff oAuthFlowDiff;
43+
private ExtensionsDiff extensionsDiff;
4344

4445
private OpenAPI oldSpecOpenApi;
4546
private OpenAPI newSpecOpenApi;
@@ -84,6 +85,7 @@ private void initializeFields() {
8485
this.securitySchemeDiff = new SecuritySchemeDiff(this);
8586
this.oAuthFlowsDiff = new OAuthFlowsDiff(this);
8687
this.oAuthFlowDiff = new OAuthFlowDiff(this);
88+
this.extensionsDiff = new ExtensionsDiff(this);
8789
}
8890

8991
private ChangedOpenApi compare() {
@@ -201,6 +203,10 @@ public OAuthFlowDiff getoAuthFlowDiff() {
201203
return oAuthFlowDiff;
202204
}
203205

206+
public ExtensionsDiff getExtensionsDiff() {
207+
return extensionsDiff;
208+
}
209+
204210
public OpenAPI getOldSpecOpenApi() {
205211
return oldSpecOpenApi;
206212
}

src/main/java/com/qdesrame/openapi/diff/compare/ParameterDiff.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected Optional<ChangedParameter> computeDiff(HashSet<String> refSet, Paramet
4646
changedParameter.setChangeAllowEmptyValue(getBooleanDiff(left.getAllowEmptyValue(), right.getAllowEmptyValue()));
4747
changedParameter.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle()));
4848
changedParameter.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
49-
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, left.getSchema(), right.getSchema(), context);
49+
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, left.getSchema(), right.getSchema(), context.copyWithRequired(true));
5050
if (changedSchema.isPresent()) {
5151
changedParameter.setChangedSchema(changedSchema.get());
5252
}

src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ArraySchemaDiffResult.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public ArraySchemaDiffResult(OpenApiDiff openApiDiff) {
2222
public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftComponents, Components rightComponents, Schema left, Schema right, DiffContext context) {
2323
ArraySchema leftArraySchema = (ArraySchema) left;
2424
ArraySchema rightArraySchema = (ArraySchema) right;
25-
return openApiDiff.getSchemaDiff().diff(refSet, leftArraySchema.getItems(), rightArraySchema.getItems(), context);
25+
return openApiDiff.getSchemaDiff().diff(refSet, leftArraySchema.getItems(), rightArraySchema.getItems(), context.copyWithRequired(true));
2626
}
2727
}

src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ComposedSchemaDiffResult.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftCompo
6666
leftSchema.set$ref(leftMapping.get(key));
6767
Schema rightSchema = new Schema();
6868
rightSchema.set$ref(rightMapping.get(key));
69-
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, leftSchema, rightSchema, context);
69+
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, leftSchema, rightSchema, context.copyWithRequired(true));
7070
changedSchema.ifPresent(schema -> changedMapping.put(key, schema));
7171
}
7272
changedSchema.setChangedOneOfSchema(changedOneOfSchema);

src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/SchemaDiffResult.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@
55
import com.qdesrame.openapi.diff.model.ChangedSchema;
66
import com.qdesrame.openapi.diff.model.DiffContext;
77
import com.qdesrame.openapi.diff.model.ListDiff;
8+
import com.qdesrame.openapi.diff.model.schema.ChangedExtensions;
89
import com.qdesrame.openapi.diff.model.schema.ChangedReadOnly;
910
import com.qdesrame.openapi.diff.model.schema.ChangedWriteOnly;
1011
import io.swagger.v3.oas.models.Components;
1112
import io.swagger.v3.oas.models.media.Schema;
1213
import lombok.Getter;
1314

14-
import java.util.HashSet;
15-
import java.util.Map;
16-
import java.util.Objects;
17-
import java.util.Optional;
15+
import java.util.*;
1816

1917
import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
2018

@@ -47,6 +45,8 @@ public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftCompo
4745
changedSchema.setChangedReadOnly(new ChangedReadOnly(context, left.getReadOnly(), right.getReadOnly()));
4846
changedSchema.setChangedWriteOnly(new ChangedWriteOnly(context, left.getWriteOnly(), right.getWriteOnly()));
4947
changedSchema.setChangedMaxLength(!Objects.equals(left.getMaxLength(), right.getMaxLength()));
48+
Optional<ChangedExtensions> changedExtensions = openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context);
49+
changedExtensions.ifPresent(changedSchema::setChangedExtensions);
5050

5151
Map<String, Schema> leftProperties = null == left ? null : left.getProperties();
5252
Map<String, Schema> rightProperties = null == right ? null : right.getProperties();
@@ -55,7 +55,7 @@ public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftCompo
5555
Map<String, Schema> missingProp = propertyDiff.getMissing();
5656

5757
for (String key : propertyDiff.getSharedKey()) {
58-
Optional<ChangedSchema> resultSchema = openApiDiff.getSchemaDiff().diff(refSet, leftProperties.get(key), rightProperties.get(key), context);
58+
Optional<ChangedSchema> resultSchema = openApiDiff.getSchemaDiff().diff(refSet, leftProperties.get(key), rightProperties.get(key), required(context, key, right.getRequired()));
5959
resultSchema.ifPresent(changedSchema1 -> changedSchema.getChangedProperties().put(key, changedSchema1));
6060
}
6161

@@ -66,6 +66,10 @@ public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftCompo
6666
return isChanged(changedSchema);
6767
}
6868

69+
private DiffContext required(DiffContext context, String key, List<String> required) {
70+
return context.copyWithRequired(required != null && required.contains(key));
71+
}
72+
6973
private void compareAdditionalProperties(HashSet<String> refSet, Schema leftSchema, Schema rightSchema, DiffContext context) {
7074
Object left = leftSchema.getAdditionalProperties();
7175
Object right = rightSchema.getAdditionalProperties();
@@ -78,7 +82,7 @@ private void compareAdditionalProperties(HashSet<String> refSet, Schema leftSche
7882
apChangedSchema.setNewSchema(rightAdditionalSchema);
7983
if (left != null && right != null) {
8084
Optional<ChangedSchema> addPropChangedSchemaOP
81-
= openApiDiff.getSchemaDiff().diff(refSet, leftAdditionalSchema, rightAdditionalSchema, context);
85+
= openApiDiff.getSchemaDiff().diff(refSet, leftAdditionalSchema, rightAdditionalSchema, context.copyWithRequired(false));
8286
apChangedSchema = addPropChangedSchemaOP.orElse(apChangedSchema);
8387
}
8488
isChanged(apChangedSchema).ifPresent(changedSchema::setAddPropChangedSchema);

0 commit comments

Comments
 (0)