Skip to content

Commit d478c28

Browse files
author
Adarsh Sharma
committed
Fixed Recursive Schema stack-overflow error
1 parent 7d26502 commit d478c28

File tree

14 files changed

+140
-38
lines changed

14 files changed

+140
-38
lines changed

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@
55
import io.swagger.v3.oas.models.media.Content;
66
import io.swagger.v3.oas.models.media.MediaType;
77

8-
import java.util.HashMap;
9-
import java.util.List;
10-
import java.util.Map;
11-
import java.util.Optional;
8+
import java.util.*;
129

1310
public class ContentDiff implements Comparable<Content> {
1411

@@ -35,7 +32,7 @@ public Optional<ChangedContent> diff(Content left, Content right) {
3532
MediaType oldMediaType = left.get(mediaTypeKey);
3633
MediaType newMediaType = right.get(mediaTypeKey);
3734
ChangedMediaType changedMediaType = new ChangedMediaType(oldMediaType.getSchema(), newMediaType.getSchema());
38-
openApiDiff.getSchemaDiff().diff(oldMediaType.getSchema(), newMediaType.getSchema()).ifPresent(changedMediaType::setChangedSchema);
35+
openApiDiff.getSchemaDiff().diff(new HashSet<>(), oldMediaType.getSchema(), newMediaType.getSchema()).ifPresent(changedMediaType::setChangedSchema);
3936
if (changedMediaType.isDiff()) {
4037
changedMediaTypes.put(mediaTypeKey, changedMediaType);
4138
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.swagger.v3.oas.models.Components;
77
import io.swagger.v3.oas.models.headers.Header;
88

9+
import java.util.HashSet;
910
import java.util.Objects;
1011
import java.util.Optional;
1112

@@ -25,11 +26,11 @@ public HeaderDiff(OpenApiDiff openApiDiff) {
2526
}
2627

2728
public Optional<ChangedHeader> diff(Header left, Header right) {
28-
return cachedDiff(left, right, left.get$ref(), right.get$ref());
29+
return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref());
2930
}
3031

3132
@Override
32-
protected Optional<ChangedHeader> computeDiff(Header left, Header right) {
33+
protected Optional<ChangedHeader> computeDiff(HashSet<String> refSet, Header left, Header right) {
3334
left = refPointer.resolveRef(leftComponents, left, left.get$ref());
3435
right = refPointer.resolveRef(rightComponents, right, right.get$ref());
3536

@@ -41,7 +42,7 @@ protected Optional<ChangedHeader> computeDiff(Header left, Header right) {
4142
changedHeader.setChangeAllowEmptyValue(getBooleanDiff(left.getAllowEmptyValue(), right.getAllowEmptyValue()));
4243
changedHeader.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle()));
4344
changedHeader.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
44-
openApiDiff.getSchemaDiff().diff(left.getSchema(), right.getSchema()).ifPresent(changedHeader::setChangedSchema);
45+
openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema()).ifPresent(changedHeader::setChangedSchema);
4546
openApiDiff.getContentDiff().diff(left.getContent(), right.getContent()).ifPresent(changedHeader::setChangedContent);
4647

4748
return changedHeader.isDiff() ? Optional.of(changedHeader) : Optional.empty();

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.swagger.v3.oas.models.Components;
88
import io.swagger.v3.oas.models.parameters.Parameter;
99

10+
import java.util.HashSet;
1011
import java.util.Objects;
1112
import java.util.Optional;
1213

@@ -24,11 +25,11 @@ public ParameterDiff(OpenApiDiff openApiDiff) {
2425
}
2526

2627
public Optional<ChangedParameter> diff(Parameter left, Parameter right) {
27-
return cachedDiff(left, right, left.get$ref(), right.get$ref());
28+
return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref());
2829
}
2930

3031
@Override
31-
protected Optional<ChangedParameter> computeDiff(Parameter left, Parameter right) {
32+
protected Optional<ChangedParameter> computeDiff(HashSet<String> refSet, Parameter left, Parameter right) {
3233
ChangedParameter changedParameter = new ChangedParameter(right.getName(), right.getIn());
3334
left = refPointer.resolveRef(this.leftComponents, left, left.get$ref());
3435
right = refPointer.resolveRef(this.rightComponents, right, right.get$ref());
@@ -42,7 +43,7 @@ protected Optional<ChangedParameter> computeDiff(Parameter left, Parameter right
4243
changedParameter.setChangeAllowEmptyValue(getBooleanDiff(left.getAllowEmptyValue(), right.getAllowEmptyValue()));
4344
changedParameter.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle()));
4445
changedParameter.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
45-
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(left.getSchema(), right.getSchema());
46+
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, left.getSchema(), right.getSchema());
4647
if (changedSchema.isPresent()) {
4748
changedParameter.setChangedSchema(changedSchema.get());
4849
}

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.qdesrame.openapi.diff.compare;
22

33
import java.util.HashMap;
4+
import java.util.HashSet;
45
import java.util.Map;
56
import java.util.Optional;
67

@@ -27,24 +28,37 @@ private void addToCache(String leftRef, String rightRef, D changed) {
2728
changedSchemaMap.put(rightRef, changed);
2829
}
2930

30-
public Optional<D> cachedDiff(C left, C right, String leftRef, String rightRef) {
31+
public Optional<D> cachedDiff(HashSet<String> refSet, C left, C right, String leftRef, String rightRef) {
3132
boolean areBothRefParameters = leftRef != null && rightRef != null;
3233
if (areBothRefParameters) {
3334
Optional<D> changedFromRef = getFromCache(leftRef, rightRef);
3435
if (changedFromRef.isPresent()) {
3536
return changedFromRef;
36-
}
37-
}
37+
} else {
38+
String refKey = getRefKey(leftRef, rightRef);
39+
if(refSet.contains(refKey)) {
40+
return Optional.empty();
41+
} else {
42+
refSet.add(refKey);
43+
Optional<D> changed = computeDiff(refSet, left, right);
3844

39-
Optional<D> changed = computeDiff(left, right);
45+
if(areBothRefParameters) {
46+
addToCache(leftRef, rightRef, changed.isPresent()? changed.get(): null);
47+
}
48+
refSet.remove(refKey);
4049

41-
if(areBothRefParameters) {
42-
addToCache(leftRef, rightRef, changed.isPresent()? changed.get(): null);
50+
return changed;
51+
}
52+
}
53+
} else {
54+
return computeDiff(refSet, left, right);
4355
}
56+
}
4457

45-
return changed;
58+
protected String getRefKey(String leftRef, String rightRef) {
59+
return leftRef + ":" + rightRef;
4660
}
4761

48-
protected abstract Optional<D> computeDiff(C left, C right);
62+
protected abstract Optional<D> computeDiff(HashSet<String> refSet, C left, C right);
4963

5064
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.swagger.v3.oas.models.media.Content;
77
import io.swagger.v3.oas.models.parameters.RequestBody;
88

9+
import java.util.HashSet;
910
import java.util.Objects;
1011
import java.util.Optional;
1112

@@ -21,11 +22,11 @@ public RequestBodyDiff(OpenApiDiff openApiDiff) {
2122
}
2223

2324
public Optional<ChangedRequestBody> diff(RequestBody left, RequestBody right) {
24-
return cachedDiff(left, right, left.get$ref(), right.get$ref());
25+
return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref());
2526
}
2627

2728
@Override
28-
protected Optional<ChangedRequestBody> computeDiff(RequestBody left, RequestBody right) {
29+
protected Optional<ChangedRequestBody> computeDiff(HashSet<String> refSet, RequestBody left, RequestBody right) {
2930
Content oldRequestContent = new Content();
3031
Content newRequestContent = new Content();
3132
RequestBody oldRequestBody = null;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.swagger.v3.oas.models.Components;
77
import io.swagger.v3.oas.models.responses.ApiResponse;
88

9+
import java.util.HashSet;
910
import java.util.Objects;
1011
import java.util.Optional;
1112

@@ -25,11 +26,11 @@ public ResponseDiff(OpenApiDiff openApiDiff) {
2526
}
2627

2728
public Optional<ChangedResponse> diff(ApiResponse left, ApiResponse right) {
28-
return cachedDiff(left, right, left.get$ref(), right.get$ref());
29+
return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref());
2930
}
3031

3132
@Override
32-
protected Optional<ChangedResponse> computeDiff(ApiResponse left, ApiResponse right) {
33+
protected Optional<ChangedResponse> computeDiff(HashSet<String> refSet, ApiResponse left, ApiResponse right) {
3334
left = refPointer.resolveRef(leftComponents, left, left.get$ref());
3435
right = refPointer.resolveRef(rightComponents, right, right.get$ref());
3536

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public SchemaDiff(OpenApiDiff openApiDiff) {
5858
this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null;
5959
}
6060

61-
public Optional<ChangedSchema> diff(Schema left, Schema right) {
62-
return cachedDiff(left, right, left.get$ref(), right.get$ref());
61+
public Optional<ChangedSchema> diff(HashSet<String> refSet, Schema left, Schema right) {
62+
return cachedDiff(refSet, left, right, left.get$ref(), right.get$ref());
6363
}
6464

6565
public Optional<ChangedSchema> getTypeChangedSchema(Schema left, Schema right) {
@@ -71,7 +71,7 @@ public Optional<ChangedSchema> getTypeChangedSchema(Schema left, Schema right) {
7171
}
7272

7373
@Override
74-
protected Optional<ChangedSchema> computeDiff(Schema left, Schema right) {
74+
protected Optional<ChangedSchema> computeDiff(HashSet<String> refSet, Schema left, Schema right) {
7575
left = refPointer.resolveRef(this.leftComponents, left, left.get$ref());
7676
right = refPointer.resolveRef(this.rightComponents, right, right.get$ref());
7777

@@ -87,7 +87,7 @@ protected Optional<ChangedSchema> computeDiff(Schema left, Schema right) {
8787

8888
//If schema type is same then get specific SchemaDiffResult and compare the properties
8989
SchemaDiffResult result = SchemaDiff.getSchemaDiffResult(right.getClass(), openApiDiff);
90-
return result.diff(leftComponents, rightComponents, left, right);
90+
return result.diff(refSet, leftComponents, rightComponents, left, right);
9191
}
9292

9393
protected static Schema resolveComposedSchema(Components components, Schema schema) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.swagger.v3.oas.models.Components;
66
import io.swagger.v3.oas.models.security.SecurityScheme;
77

8+
import java.util.HashSet;
89
import java.util.List;
910
import java.util.Objects;
1011
import java.util.Optional;
@@ -26,7 +27,7 @@ public SecuritySchemeDiff(OpenApiDiff openApiDiff) {
2627
public Optional<ChangedSecurityScheme> diff(String leftSchemeRef, List<String> leftScopes, String rightSchemeRef, List<String> rightScopes) {
2728
SecurityScheme leftSecurityScheme = leftComponents.getSecuritySchemes().get(leftSchemeRef);
2829
SecurityScheme rightSecurityScheme = rightComponents.getSecuritySchemes().get(rightSchemeRef);
29-
Optional<ChangedSecurityScheme> changedSecuritySchemeOpt = cachedDiff(leftSecurityScheme, rightSecurityScheme, leftSchemeRef, rightSchemeRef);
30+
Optional<ChangedSecurityScheme> changedSecuritySchemeOpt = cachedDiff(new HashSet<>(), leftSecurityScheme, rightSecurityScheme, leftSchemeRef, rightSchemeRef);
3031
ChangedSecurityScheme changedSecurityScheme = changedSecuritySchemeOpt.orElse(new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme));
3132
changedSecurityScheme = getCopyWithoutScopes(changedSecurityScheme);
3233

@@ -41,7 +42,7 @@ public Optional<ChangedSecurityScheme> diff(String leftSchemeRef, List<String> l
4142
}
4243

4344
@Override
44-
protected Optional<ChangedSecurityScheme> computeDiff(SecurityScheme leftSecurityScheme, SecurityScheme rightSecurityScheme) {
45+
protected Optional<ChangedSecurityScheme> computeDiff(HashSet<String> refSet, SecurityScheme leftSecurityScheme, SecurityScheme rightSecurityScheme) {
4546
ChangedSecurityScheme changedSecurityScheme = new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme);
4647

4748
changedSecurityScheme.setChangedDescription(!Objects.equals(leftSecurityScheme.getDescription(), rightSecurityScheme.getDescription()));

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.swagger.v3.oas.models.media.ArraySchema;
77
import io.swagger.v3.oas.models.media.Schema;
88

9+
import java.util.HashSet;
910
import java.util.Optional;
1011

1112
/**
@@ -17,9 +18,9 @@ public ArraySchemaDiffResult(OpenApiDiff openApiDiff) {
1718
}
1819

1920
@Override
20-
public Optional<ChangedSchema> diff(Components leftComponents, Components rightComponents, Schema left, Schema right) {
21+
public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftComponents, Components rightComponents, Schema left, Schema right) {
2122
ArraySchema leftArraySchema = (ArraySchema) left;
2223
ArraySchema rightArraySchema = (ArraySchema) right;
23-
return openApiDiff.getSchemaDiff().diff(leftArraySchema.getItems(), rightArraySchema.getItems());
24+
return openApiDiff.getSchemaDiff().diff(refSet, leftArraySchema.getItems(), rightArraySchema.getItems());
2425
}
2526
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
package com.qdesrame.openapi.diff.compare.schemadiffresult;
22

33
import com.qdesrame.openapi.diff.compare.MapKeyDiff;
4-
import com.qdesrame.openapi.diff.utils.RefPointer;
54
import com.qdesrame.openapi.diff.compare.OpenApiDiff;
6-
import com.qdesrame.openapi.diff.utils.RefType;
75
import com.qdesrame.openapi.diff.model.ChangedOneOfSchema;
86
import com.qdesrame.openapi.diff.model.ChangedSchema;
7+
import com.qdesrame.openapi.diff.utils.RefPointer;
8+
import com.qdesrame.openapi.diff.utils.RefType;
99
import io.swagger.v3.oas.models.Components;
1010
import io.swagger.v3.oas.models.media.ComposedSchema;
1111
import io.swagger.v3.oas.models.media.Discriminator;
1212
import io.swagger.v3.oas.models.media.Schema;
1313
import org.apache.commons.collections4.CollectionUtils;
1414

1515
import java.util.HashMap;
16+
import java.util.HashSet;
1617
import java.util.Map;
1718
import java.util.Optional;
1819
import java.util.stream.Collectors;
@@ -28,7 +29,7 @@ public ComposedSchemaDiffResult(OpenApiDiff openApiDiff) {
2829
}
2930

3031
@Override
31-
public Optional<ChangedSchema> diff(Components leftComponents, Components rightComponents, Schema left, Schema right) {
32+
public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftComponents, Components rightComponents, Schema left, Schema right) {
3233
if(left instanceof ComposedSchema) {
3334
ComposedSchema leftComposedSchema = (ComposedSchema) left;
3435
ComposedSchema rightComposedSchema = (ComposedSchema) right;
@@ -63,14 +64,14 @@ public Optional<ChangedSchema> diff(Components leftComponents, Components rightC
6364
leftSchema.set$ref(leftMapping.get(key));
6465
Schema rightSchema = new Schema();
6566
rightSchema.set$ref(rightMapping.get(key));
66-
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(leftSchema, rightSchema);
67+
Optional<ChangedSchema> changedSchema = openApiDiff.getSchemaDiff().diff(refSet, leftSchema, rightSchema);
6768
if (changedSchema.isPresent() && changedSchema.get().isDiff()) {
6869
changedMapping.put(key, changedSchema.get());
6970
}
7071
}
7172
changedSchema.setChangedOneOfSchema(changedOneOfSchema);
7273
}
73-
return super.diff(leftComponents, rightComponents, left, right);
74+
return super.diff(refSet, leftComponents, rightComponents, left, right);
7475
} else {
7576
return openApiDiff.getSchemaDiff().getTypeChangedSchema(left, right);
7677
}

0 commit comments

Comments
 (0)