From 4d0f20d95d8e488b07142feb74d059fe8b9ba99e Mon Sep 17 00:00:00 2001 From: Quentin Desrame Date: Wed, 18 Apr 2018 19:03:53 +0200 Subject: [PATCH 1/4] Update data model to manage diff context && to return result instead of boolean --- .../java/com/qdesrame/openapi/diff/Main.java | 4 +- .../openapi/diff/compare/ApiResponseDiff.java | 14 +- .../openapi/diff/compare/ContentDiff.java | 16 ++- .../openapi/diff/compare/HeaderDiff.java | 17 ++- .../openapi/diff/compare/HeadersDiff.java | 11 +- .../openapi/diff/compare/OAuthFlowDiff.java | 4 +- .../openapi/diff/compare/OAuthFlowsDiff.java | 4 +- .../openapi/diff/compare/OperationDiff.java | 20 +-- .../openapi/diff/compare/ParameterDiff.java | 17 ++- .../openapi/diff/compare/ParametersDiff.java | 11 +- .../openapi/diff/compare/PathDiff.java | 12 +- .../openapi/diff/compare/PathsDiff.java | 10 +- .../diff/compare/ReferenceDiffCache.java | 21 +-- .../openapi/diff/compare/RequestBodyDiff.java | 17 ++- .../openapi/diff/compare/ResponseDiff.java | 17 ++- .../openapi/diff/compare/SchemaDiff.java | 30 +++- .../diff/compare/SecurityRequirementDiff.java | 9 +- .../compare/SecurityRequirementsDiff.java | 9 +- .../diff/compare/SecuritySchemeDiff.java | 11 +- .../ArraySchemaDiffResult.java | 5 +- .../ComposedSchemaDiffResult.java | 15 +- .../schemadiffresult/SchemaDiffResult.java | 25 ++-- .../qdesrame/openapi/diff/model/Changed.java | 18 ++- .../diff/model/ChangedApiResponse.java | 24 ++-- .../openapi/diff/model/ChangedContent.java | 27 ++-- .../openapi/diff/model/ChangedHeader.java | 36 +++-- .../openapi/diff/model/ChangedHeaders.java | 26 ++-- .../openapi/diff/model/ChangedMediaType.java | 25 ++-- .../openapi/diff/model/ChangedOAuthFlow.java | 17 +-- .../openapi/diff/model/ChangedOAuthFlows.java | 30 ++-- .../diff/model/ChangedOneOfSchema.java | 27 ++-- .../openapi/diff/model/ChangedOpenApi.java | 19 ++- .../openapi/diff/model/ChangedOperation.java | 37 ++--- .../openapi/diff/model/ChangedParameter.java | 37 ++--- .../openapi/diff/model/ChangedParameters.java | 25 ++-- .../openapi/diff/model/ChangedPath.java | 26 ++-- .../openapi/diff/model/ChangedPaths.java | 19 +-- .../diff/model/ChangedRequestBody.java | 24 ++-- .../openapi/diff/model/ChangedResponse.java | 27 ++-- .../openapi/diff/model/ChangedSchema.java | 52 +++---- .../model/ChangedSecurityRequirement.java | 22 +-- .../model/ChangedSecurityRequirements.java | 19 ++- .../diff/model/ChangedSecurityScheme.java | 33 ++--- .../openapi/diff/model/DiffContext.java | 21 +++ .../openapi/diff/model/DiffResult.java | 34 +++++ .../qdesrame/openapi/diff/model/ListDiff.java | 4 + .../diff/model/RequestResponseChanged.java | 9 -- .../openapi/diff/output/ConsoleRender.java | 13 +- .../openapi/diff/output/HtmlRender.java | 6 +- .../openapi/diff/output/MarkdownRender.java | 6 +- .../openapi/diff/utils/ChangedUtils.java | 23 +++ .../test/BackwardCompatibilityTest.java | 6 + .../openapi/test/ResponseHeaderDiffTest.java | 2 +- .../openapi/test/SecurityDiffTest.java | 10 +- .../com/qdesrame/openapi/test/TestUtils.java | 16 ++- .../resources/backwardCompatibility/bc_1.yaml | 3 + .../resources/backwardCompatibility/bc_5.yaml | 131 ++++++++++++++++++ 57 files changed, 732 insertions(+), 421 deletions(-) create mode 100644 src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java create mode 100644 src/main/java/com/qdesrame/openapi/diff/model/DiffResult.java delete mode 100644 src/main/java/com/qdesrame/openapi/diff/model/RequestResponseChanged.java create mode 100644 src/main/java/com/qdesrame/openapi/diff/utils/ChangedUtils.java create mode 100644 src/test/resources/backwardCompatibility/bc_5.yaml diff --git a/src/main/java/com/qdesrame/openapi/diff/Main.java b/src/main/java/com/qdesrame/openapi/diff/Main.java index 2dd52036e..7dc6b3531 100644 --- a/src/main/java/com/qdesrame/openapi/diff/Main.java +++ b/src/main/java/com/qdesrame/openapi/diff/Main.java @@ -131,10 +131,10 @@ public static void main(String... args) { } } if (line.hasOption("state")) { - System.out.println(result.isDiff() ? result.isDiffBackwardCompatible() ? "compatible" : "incompatible" : "no_changes"); + System.out.println(result.isChanged().getValue()); System.exit(0); } else { - System.exit(result.isDiff() ? 1 : 0); + System.exit(result.isUnchanged() ? 0 : 1); } } catch (ParseException e) { // oops, something went wrong diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java index ac2626d8b..7cdf5b974 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java @@ -2,6 +2,7 @@ import com.qdesrame.openapi.diff.model.ChangedApiResponse; import com.qdesrame.openapi.diff.model.ChangedResponse; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; @@ -10,6 +11,8 @@ import java.util.Map; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 04/01/18. */ @@ -20,19 +23,20 @@ public ApiResponseDiff(OpenApiDiff openApiDiff) { this.openApiDiff = openApiDiff; } - public Optional diff(ApiResponses left, ApiResponses right) { + public Optional diff(ApiResponses left, ApiResponses right, DiffContext context) { MapKeyDiff responseMapKeyDiff = MapKeyDiff.diff(left, right); - ChangedApiResponse changedApiResponse = new ChangedApiResponse(left, right); + ChangedApiResponse changedApiResponse = new ChangedApiResponse(left, right, context); changedApiResponse.setAddResponses(responseMapKeyDiff.getIncreased()); changedApiResponse.setMissingResponses(responseMapKeyDiff.getMissing()); List sharedResponseCodes = responseMapKeyDiff.getSharedKey(); - + context.setRequest(false); + context.setResponse(true); Map resps = new HashMap<>(); for (String responseCode : sharedResponseCodes) { - openApiDiff.getResponseDiff().diff(left.get(responseCode), right.get(responseCode)) + openApiDiff.getResponseDiff().diff(left.get(responseCode), right.get(responseCode), context) .ifPresent(changedResponse -> resps.put(responseCode, changedResponse)); } changedApiResponse.setChangedResponses(resps); - return changedApiResponse.isDiff() ? Optional.of(changedApiResponse) : Optional.empty(); + return isChanged(changedApiResponse); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ContentDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ContentDiff.java index a9754fdc5..145118065 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ContentDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ContentDiff.java @@ -2,11 +2,15 @@ import com.qdesrame.openapi.diff.model.ChangedContent; import com.qdesrame.openapi.diff.model.ChangedMediaType; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; import java.util.*; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isUnchanged; + public class ContentDiff implements Comparable { private OpenApiDiff openApiDiff; @@ -20,8 +24,8 @@ public boolean compare(Content left, Content right) { return false; } - public Optional diff(Content left, Content right) { - ChangedContent changedContent = new ChangedContent(left, right); + public Optional diff(Content left, Content right, DiffContext context) { + ChangedContent changedContent = new ChangedContent(left, right, context); MapKeyDiff mediaTypeDiff = MapKeyDiff.diff(left, right); changedContent.setIncreased(mediaTypeDiff.getIncreased()); @@ -31,13 +35,13 @@ public Optional diff(Content left, Content right) { for (String mediaTypeKey : sharedMediaTypes) { MediaType oldMediaType = left.get(mediaTypeKey); MediaType newMediaType = right.get(mediaTypeKey); - ChangedMediaType changedMediaType = new ChangedMediaType(oldMediaType.getSchema(), newMediaType.getSchema()); - openApiDiff.getSchemaDiff().diff(new HashSet<>(), oldMediaType.getSchema(), newMediaType.getSchema()).ifPresent(changedMediaType::setChangedSchema); - if (changedMediaType.isDiff()) { + ChangedMediaType changedMediaType = new ChangedMediaType(oldMediaType.getSchema(), newMediaType.getSchema(), context); + openApiDiff.getSchemaDiff().diff(new HashSet<>(), oldMediaType.getSchema(), newMediaType.getSchema(), context).ifPresent(changedMediaType::setChangedSchema); + if (!isUnchanged(changedMediaType)) { changedMediaTypes.put(mediaTypeKey, changedMediaType); } } changedContent.setChanged(changedMediaTypes); - return changedContent.isDiff() ? Optional.of(changedContent) : Optional.empty(); + return isChanged(changedContent); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/HeaderDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/HeaderDiff.java index f15badf47..b2a6c6dbd 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/HeaderDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/HeaderDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedHeader; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -10,6 +11,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 28/12/17. */ @@ -25,26 +28,26 @@ public HeaderDiff(OpenApiDiff openApiDiff) { this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null; } - public Optional diff(Header left, Header right) { - return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref()); + public Optional diff(Header left, Header right, DiffContext context) { + return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref(), context); } @Override - protected Optional computeDiff(HashSet refSet, Header left, Header right) { + protected Optional computeDiff(HashSet refSet, Header left, Header right, DiffContext context) { left = refPointer.resolveRef(leftComponents, left, left.get$ref()); right = refPointer.resolveRef(rightComponents, right, right.get$ref()); - ChangedHeader changedHeader = new ChangedHeader(left, right); + ChangedHeader changedHeader = new ChangedHeader(left, right, context); changedHeader.setChangeDescription(!Objects.equals(left.getDescription(), right.getDescription())); changedHeader.setChangeRequired(getBooleanDiff(left.getRequired(), right.getRequired())); changedHeader.setChangeDeprecated(!Boolean.TRUE.equals(left.getDeprecated()) && Boolean.TRUE.equals(right.getDeprecated())); changedHeader.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle())); changedHeader.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode())); - openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema()).ifPresent(changedHeader::setChangedSchema); - openApiDiff.getContentDiff().diff(left.getContent(), right.getContent()).ifPresent(changedHeader::setChangedContent); + openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema(), context).ifPresent(changedHeader::setChangedSchema); + openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context).ifPresent(changedHeader::setChangedContent); - return changedHeader.isDiff() ? Optional.of(changedHeader) : Optional.empty(); + return isChanged(changedHeader); } private boolean getBooleanDiff(Boolean left, Boolean right) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/HeadersDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/HeadersDiff.java index 58c990dcf..9e39a0306 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/HeadersDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/HeadersDiff.java @@ -2,6 +2,7 @@ import com.qdesrame.openapi.diff.model.ChangedHeader; import com.qdesrame.openapi.diff.model.ChangedHeaders; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.headers.Header; import java.util.HashMap; @@ -9,6 +10,8 @@ import java.util.Map; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 28/12/17. */ @@ -19,8 +22,8 @@ public HeadersDiff(OpenApiDiff openApiDiff) { this.openApiDiff = openApiDiff; } - public Optional diff(Map left, Map right) { - ChangedHeaders changedHeaders = new ChangedHeaders(left, right); + public Optional diff(Map left, Map right, DiffContext context) { + ChangedHeaders changedHeaders = new ChangedHeaders(left, right, context); MapKeyDiff headerMapDiff = MapKeyDiff.diff(left, right); changedHeaders.setIncreased(headerMapDiff.getIncreased()); changedHeaders.setMissing(headerMapDiff.getMissing()); @@ -30,11 +33,11 @@ public Optional diff(Map left, Map changed.put(headerKey, changedHeader)); } changedHeaders.setChanged(changed); - return changedHeaders.isDiff() ? Optional.of(changedHeaders) : Optional.empty(); + return isChanged(changedHeaders); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowDiff.java index 52a07326f..68d5d2cc0 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowDiff.java @@ -6,6 +6,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 12/01/18. */ @@ -24,6 +26,6 @@ public Optional diff(OAuthFlow left, OAuthFlow right) { changedOAuthFlow.setChangedRefreshUrl(!Objects.equals(left.getRefreshUrl(), right.getRefreshUrl())); } - return changedOAuthFlow.isDiff() ? Optional.of(changedOAuthFlow) : Optional.empty(); + return isChanged(changedOAuthFlow); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowsDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowsDiff.java index 5a83b714e..ae3235a11 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowsDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/OAuthFlowsDiff.java @@ -5,6 +5,8 @@ import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 12/01/18. */ @@ -23,6 +25,6 @@ public Optional diff(OAuthFlows left, OAuthFlows right) { openApiDiff.getoAuthFlowDiff().diff(left.getClientCredentials(), right.getClientCredentials()).ifPresent(changedOAuthFlows::setChangedClientCredentialOAuthFlow); openApiDiff.getoAuthFlowDiff().diff(left.getAuthorizationCode(), right.getAuthorizationCode()).ifPresent(changedOAuthFlows::setChangedAuthorizationCodeOAuthFlow); } - return changedOAuthFlows.isDiff() ? Optional.of(changedOAuthFlows) : Optional.empty(); + return isChanged(changedOAuthFlows); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java index 8f1c30874..cc50534ee 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java @@ -2,14 +2,16 @@ import com.qdesrame.openapi.diff.model.ChangedOperation; import com.qdesrame.openapi.diff.model.ChangedParameters; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.parameters.Parameter; import java.util.List; import java.util.Map; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 04/01/18. */ @@ -20,34 +22,34 @@ public OperationDiff(OpenApiDiff openApiDiff) { this.openApiDiff = openApiDiff; } - public Optional diff(String pathUrl, PathItem.HttpMethod method, Map pathParameters, Operation oldOperation, Operation newOperation) { - ChangedOperation changedOperation = new ChangedOperation(pathUrl, method, oldOperation, newOperation); + public Optional diff(Operation oldOperation, Operation newOperation, DiffContext context) { + ChangedOperation changedOperation = new ChangedOperation(context.getUrl(), context.getMethod(), oldOperation, newOperation); changedOperation.setSummary(newOperation.getSummary()); changedOperation.setDeprecated(!Boolean.TRUE.equals(oldOperation.getDeprecated()) && Boolean.TRUE.equals(newOperation.getDeprecated())); if (oldOperation.getRequestBody() != null || newOperation.getRequestBody() != null) { - openApiDiff.getRequestBodyDiff().diff(oldOperation.getRequestBody(), newOperation.getRequestBody()) + openApiDiff.getRequestBodyDiff().diff(oldOperation.getRequestBody(), newOperation.getRequestBody(), context) .ifPresent(changedOperation::setChangedRequestBody); } - openApiDiff.getParametersDiff().diff(oldOperation.getParameters(), newOperation.getParameters()) + openApiDiff.getParametersDiff().diff(oldOperation.getParameters(), newOperation.getParameters(), context) .ifPresent(params -> { - removePathParameters(pathParameters, params); + removePathParameters(context.getParameters(), params); changedOperation.setChangedParameters(params); }); if (oldOperation.getResponses() != null || newOperation.getResponses() != null) { - openApiDiff.getApiResponseDiff().diff(oldOperation.getResponses(), newOperation.getResponses()) + openApiDiff.getApiResponseDiff().diff(oldOperation.getResponses(), newOperation.getResponses(), context) .ifPresent(changedOperation::setChangedApiResponse); } if (oldOperation.getSecurity() != null || newOperation.getSecurity() != null) { - openApiDiff.getSecurityRequirementsDiff().diff(oldOperation.getSecurity(), newOperation.getSecurity()) + openApiDiff.getSecurityRequirementsDiff().diff(oldOperation.getSecurity(), newOperation.getSecurity(), context) .ifPresent(changedOperation::setChangedSecurityRequirements); } - return changedOperation.isDiff() ? Optional.of(changedOperation) : Optional.empty(); + return isChanged(changedOperation); } public void removePathParameters(Map pathParameters, ChangedParameters params) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ParameterDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ParameterDiff.java index 7cea0df62..25bdedb69 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ParameterDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ParameterDiff.java @@ -2,6 +2,7 @@ import com.qdesrame.openapi.diff.model.ChangedParameter; import com.qdesrame.openapi.diff.model.ChangedSchema; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -11,6 +12,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + public class ParameterDiff extends ReferenceDiffCache { private Components leftComponents; @@ -24,13 +27,13 @@ public ParameterDiff(OpenApiDiff openApiDiff) { this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null; } - public Optional diff(Parameter left, Parameter right) { - return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref()); + public Optional diff(Parameter left, Parameter right, DiffContext context) { + return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref(), context); } @Override - protected Optional computeDiff(HashSet refSet, Parameter left, Parameter right) { - ChangedParameter changedParameter = new ChangedParameter(right.getName(), right.getIn()); + protected Optional computeDiff(HashSet refSet, Parameter left, Parameter right, DiffContext context) { + ChangedParameter changedParameter = new ChangedParameter(right.getName(), right.getIn(), context); left = refPointer.resolveRef(this.leftComponents, left, left.get$ref()); right = refPointer.resolveRef(this.rightComponents, right, right.get$ref()); @@ -43,14 +46,14 @@ protected Optional computeDiff(HashSet refSet, Paramet changedParameter.setChangeAllowEmptyValue(getBooleanDiff(left.getAllowEmptyValue(), right.getAllowEmptyValue())); changedParameter.setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle())); changedParameter.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode())); - Optional changedSchema = openApiDiff.getSchemaDiff().diff(refSet, left.getSchema(), right.getSchema()); + Optional changedSchema = openApiDiff.getSchemaDiff().diff(refSet, left.getSchema(), right.getSchema(), context); if (changedSchema.isPresent()) { changedParameter.setChangedSchema(changedSchema.get()); } - openApiDiff.getContentDiff().diff(left.getContent(), right.getContent()) + openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context) .ifPresent(changedParameter::setChangedContent); - return changedParameter.isDiff() ? Optional.of(changedParameter) : Optional.empty(); + return isChanged(changedParameter); } private boolean getBooleanDiff(Boolean left, Boolean right) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ParametersDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ParametersDiff.java index 12009be19..f2c50c7c7 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ParametersDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ParametersDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedParameters; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -11,6 +12,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * compare two parameter * @@ -37,8 +40,8 @@ public static boolean same(Parameter left, Parameter right) { return Objects.equals(left.getName(), right.getName()) && Objects.equals(left.getIn(), right.getIn()); } - public Optional diff(List left, List right) { - ChangedParameters changedParameters = new ChangedParameters(left, right != null ? new ArrayList<>(right) : null); + public Optional diff(List left, List right, DiffContext context) { + ChangedParameters changedParameters = new ChangedParameters(left, right != null ? new ArrayList<>(right) : null, context); if (null == left) left = new ArrayList<>(); if (null == right) right = new ArrayList<>(); @@ -51,11 +54,11 @@ public Optional diff(List left, List ri } else { Parameter rightPara = rightParam.get(); right.remove(rightPara); - openApiDiff.getParameterDiff().diff(leftPara, rightPara).ifPresent(changedParameters.getChanged()::add); + openApiDiff.getParameterDiff().diff(leftPara, rightPara, context).ifPresent(changedParameters.getChanged()::add); } } changedParameters.getIncreased().addAll(right); - return changedParameters.isDiff() ? Optional.of(changedParameters) : Optional.empty(); + return isChanged(changedParameters); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java index 73a9d59ad..ea87f7cce 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedPath; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -8,6 +9,8 @@ import java.util.Map; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + public class PathDiff { private OpenApiDiff openApiDiff; @@ -15,8 +18,8 @@ public PathDiff(OpenApiDiff openApiDiff) { this.openApiDiff = openApiDiff; } - public Optional diff(String pathUrl, Map pathParameters, PathItem left, PathItem right) { - ChangedPath changedPath = new ChangedPath(pathUrl, left, right); + public Optional diff(PathItem left, PathItem right, DiffContext context) { + ChangedPath changedPath = new ChangedPath(context.getUrl(), left, right, context); Map oldOperationMap = left.readOperationsMap(); Map newOperationMap = right.readOperationsMap(); @@ -28,8 +31,9 @@ public Optional diff(String pathUrl, Map pathParame for (PathItem.HttpMethod method : sharedMethods) { Operation oldOperation = oldOperationMap.get(method); Operation newOperation = newOperationMap.get(method); - openApiDiff.getOperationDiff().diff(pathUrl, method, pathParameters, oldOperation, newOperation).ifPresent(changedPath.getChanged()::add); + context.setMethod(method); + openApiDiff.getOperationDiff().diff(oldOperation, newOperation, context).ifPresent(changedPath.getChanged()::add); } - return changedPath.isDiff() ? Optional.of(changedPath) : Optional.empty(); + return isChanged(changedPath); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/PathsDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/PathsDiff.java index 724b83c09..731d3f113 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/PathsDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/PathsDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedPaths; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.Paths; @@ -8,6 +9,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + public class PathsDiff { private static final String REGEX_PATH = "\\{([^/]+)\\}"; private OpenApiDiff openApiDiff; @@ -50,12 +53,15 @@ public Optional diff(final Map left, final Map changedPaths.getChanged().put(result.get(), path)); + DiffContext context = new DiffContext(); + context.setUrl(url); + context.setParameters(params); + openApiDiff.getPathDiff().diff(leftPath, rightPath, context).ifPresent(path -> changedPaths.getChanged().put(result.get(), path)); } else { changedPaths.getMissing().put(url, leftPath); } }); - return changedPaths.isDiff() ? Optional.of(changedPaths) : Optional.empty(); + return isChanged(changedPaths); } public static Paths valOrEmpty(Paths path) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java b/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java index 53a61a22c..69fbc7a01 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java @@ -1,5 +1,7 @@ package com.qdesrame.openapi.diff.compare; +import com.qdesrame.openapi.diff.model.DiffContext; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -28,7 +30,11 @@ private void addToCache(String leftRef, String rightRef, D changed) { changedSchemaMap.put(rightRef, changed); } - public Optional cachedDiff(HashSet refSet, C left, C right, String leftRef, String rightRef) { + // public Optional cachedDiff(HashSet refSet, C left, C right, String leftRef, String rightRef) { +// return cachedDiff(refSet, left, right, leftRef, rightRef, null); +// } +// + public Optional cachedDiff(HashSet refSet, C left, C right, String leftRef, String rightRef, DiffContext context) { boolean areBothRefParameters = leftRef != null && rightRef != null; if (areBothRefParameters) { Optional changedFromRef = getFromCache(leftRef, rightRef); @@ -36,22 +42,19 @@ public Optional cachedDiff(HashSet refSet, C left, C right, String le return changedFromRef; } else { String refKey = getRefKey(leftRef, rightRef); - if(refSet.contains(refKey)) { + if (refSet.contains(refKey)) { return Optional.empty(); } else { refSet.add(refKey); - Optional changed = computeDiff(refSet, left, right); - - if(areBothRefParameters) { - addToCache(leftRef, rightRef, changed.isPresent()? changed.get(): null); - } + Optional changed = computeDiff(refSet, left, right, context); + addToCache(leftRef, rightRef, changed.orElse(null)); refSet.remove(refKey); return changed; } } } else { - return computeDiff(refSet, left, right); + return computeDiff(refSet, left, right, context); } } @@ -59,6 +62,6 @@ protected String getRefKey(String leftRef, String rightRef) { return leftRef + ":" + rightRef; } - protected abstract Optional computeDiff(HashSet refSet, C left, C right); + protected abstract Optional computeDiff(HashSet refSet, C left, C right, DiffContext context); } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java index 532408d92..1ce7df07b 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedRequestBody; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.media.Content; @@ -10,6 +11,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 28/12/17. */ @@ -21,12 +24,12 @@ public RequestBodyDiff(OpenApiDiff openApiDiff) { this.openApiDiff = openApiDiff; } - public Optional diff(RequestBody left, RequestBody right) { - return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref()); + public Optional diff(RequestBody left, RequestBody right, DiffContext context) { + return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref(), context); } @Override - protected Optional computeDiff(HashSet refSet, RequestBody left, RequestBody right) { + protected Optional computeDiff(HashSet refSet, RequestBody left, RequestBody right, DiffContext context) { Content oldRequestContent = new Content(); Content newRequestContent = new Content(); RequestBody oldRequestBody = null; @@ -43,8 +46,10 @@ protected Optional computeDiff(HashSet refSet, Reque newRequestContent = newRequestBody.getContent(); } } + context.setRequest(true); + context.setResponse(false); - ChangedRequestBody changedRequestBody = new ChangedRequestBody(oldRequestBody, newRequestBody); + ChangedRequestBody changedRequestBody = new ChangedRequestBody(oldRequestBody, newRequestBody, context); boolean leftRequired = oldRequestBody != null && Boolean.TRUE.equals(oldRequestBody.getRequired()); boolean rightRequired = newRequestBody != null && Boolean.TRUE.equals(newRequestBody.getRequired()); @@ -54,8 +59,8 @@ protected Optional computeDiff(HashSet refSet, Reque String rightDescription = newRequestBody != null ? newRequestBody.getDescription() : null; changedRequestBody.setChangeDescription(!Objects.equals(leftDescription, rightDescription)); - openApiDiff.getContentDiff().diff(oldRequestContent, newRequestContent).ifPresent(changedRequestBody::setChangedContent); + openApiDiff.getContentDiff().diff(oldRequestContent, newRequestContent, context).ifPresent(changedRequestBody::setChangedContent); - return changedRequestBody.isDiff() ? Optional.of(changedRequestBody) : Optional.empty(); + return isChanged(changedRequestBody); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ResponseDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ResponseDiff.java index 7ee3995a3..eec3520c7 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ResponseDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ResponseDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedResponse; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -10,6 +11,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 28/12/17. */ @@ -25,21 +28,21 @@ public ResponseDiff(OpenApiDiff openApiDiff) { this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null; } - public Optional diff(ApiResponse left, ApiResponse right) { - return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref()); + public Optional diff(ApiResponse left, ApiResponse right, DiffContext context) { + return cachedDiff(new HashSet<>(), left, right, left.get$ref(), right.get$ref(), context); } @Override - protected Optional computeDiff(HashSet refSet, ApiResponse left, ApiResponse right) { + protected Optional computeDiff(HashSet refSet, ApiResponse left, ApiResponse right, DiffContext context) { left = refPointer.resolveRef(leftComponents, left, left.get$ref()); right = refPointer.resolveRef(rightComponents, right, right.get$ref()); - ChangedResponse changedResponse = new ChangedResponse(left, right); + ChangedResponse changedResponse = new ChangedResponse(left, right, context); - openApiDiff.getContentDiff().diff(left.getContent(), right.getContent()).ifPresent(changedResponse::setChangedContent); - openApiDiff.getHeadersDiff().diff(left.getHeaders(), right.getHeaders()).ifPresent(changedResponse::setChangedHeaders); + openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context).ifPresent(changedResponse::setChangedContent); + openApiDiff.getHeadersDiff().diff(left.getHeaders(), right.getHeaders(), context).ifPresent(changedResponse::setChangedHeaders); changedResponse.setChangeDescription(!Objects.equals(left.getDescription(), right.getDescription())); - return changedResponse.isDiff() ? Optional.of(changedResponse) : Optional.empty(); + return isChanged(changedResponse); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/SchemaDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/SchemaDiff.java index 512dc69ba..9c587bf2c 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/SchemaDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/SchemaDiff.java @@ -4,6 +4,7 @@ import com.qdesrame.openapi.diff.compare.schemadiffresult.ComposedSchemaDiffResult; import com.qdesrame.openapi.diff.compare.schemadiffresult.SchemaDiffResult; import com.qdesrame.openapi.diff.model.ChangedSchema; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -58,20 +59,21 @@ public SchemaDiff(OpenApiDiff openApiDiff) { this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null; } - public Optional diff(HashSet refSet, Schema left, Schema right) { - return cachedDiff(refSet, left, right, left.get$ref(), right.get$ref()); + public Optional diff(HashSet refSet, Schema left, Schema right, DiffContext context) { + return cachedDiff(refSet, left, right, left.get$ref(), right.get$ref(), context); } - public Optional getTypeChangedSchema(Schema left, Schema right) { + public Optional getTypeChangedSchema(Schema left, Schema right, DiffContext context) { ChangedSchema changedSchema = SchemaDiff.getSchemaDiffResult(openApiDiff).getChangedSchema(); changedSchema.setOldSchema(left); changedSchema.setNewSchema(right); changedSchema.setChangedType(true); + changedSchema.setContext(context); return Optional.of(changedSchema); } @Override - protected Optional computeDiff(HashSet refSet, Schema left, Schema right) { + protected Optional computeDiff(HashSet refSet, Schema left, Schema right, DiffContext context) { left = refPointer.resolveRef(this.leftComponents, left, left.get$ref()); right = refPointer.resolveRef(this.rightComponents, right, right.get$ref()); @@ -82,12 +84,28 @@ protected Optional computeDiff(HashSet refSet, Schema lef // return the object if (!Objects.equals(left.getType(), right.getType()) || !Objects.equals(left.getFormat(), right.getFormat())) { - return getTypeChangedSchema(left, right); + return getTypeChangedSchema(left, right, context); } //If schema type is same then get specific SchemaDiffResult and compare the properties SchemaDiffResult result = SchemaDiff.getSchemaDiffResult(right.getClass(), openApiDiff); - return result.diff(refSet, leftComponents, rightComponents, left, right); + Optional schema = result.diff(refSet, leftComponents, rightComponents, left, right, context); + if (schema.isPresent()) { + if (context.isResponse()) { + if (Boolean.TRUE.equals(schema.get().getNewSchema().getWriteOnly())) { + if (!schema.get().isChangeWriteOnly()) { + schema = Optional.empty(); + } + } + } else if (context.isRequest()) { + if (Boolean.TRUE.equals(schema.get().getNewSchema().getReadOnly())) { + if (!schema.get().isChangeReadOnly()) { + schema = Optional.empty(); + } + } + } + } + return schema; } protected static Schema resolveComposedSchema(Components components, Schema schema) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementDiff.java index 6d93bbaa3..b25471c35 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementDiff.java @@ -2,12 +2,15 @@ import com.qdesrame.openapi.diff.model.ChangedSecurityRequirement; import com.qdesrame.openapi.diff.model.ChangedSecurityScheme; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import java.util.*; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 07/01/18. */ @@ -49,7 +52,7 @@ private LinkedHashMap> contains(SecurityRequirement right, return found; } - public Optional diff(SecurityRequirement left, SecurityRequirement right) { + public Optional diff(SecurityRequirement left, SecurityRequirement right, DiffContext context) { ChangedSecurityRequirement changedSecurityRequirement = new ChangedSecurityRequirement(left, right != null ? getCopy(right) : null); @@ -64,13 +67,13 @@ public Optional diff(SecurityRequirement left, Secur String rightSchemeRef = rightSec.keySet().stream().findFirst().get(); right.remove(rightSchemeRef); Optional diff = openApiDiff.getSecuritySchemeDiff() - .diff(leftSchemeRef, left.get(leftSchemeRef), rightSchemeRef, rightSec.get(rightSchemeRef)); + .diff(leftSchemeRef, left.get(leftSchemeRef), rightSchemeRef, rightSec.get(rightSchemeRef), context); diff.ifPresent(changedSecurityRequirement::addChanged); } } right.entrySet().stream().forEach(x -> changedSecurityRequirement.addIncreased(x.getKey(), x.getValue())); - return changedSecurityRequirement.isDiff() ? Optional.of(changedSecurityRequirement) : Optional.empty(); + return isChanged(changedSecurityRequirement); } public static SecurityRequirement getCopy(LinkedHashMap> right) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementsDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementsDiff.java index edbd920d9..42dc5e6ba 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementsDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/SecurityRequirementsDiff.java @@ -2,6 +2,7 @@ import com.qdesrame.openapi.diff.model.ChangedSecurityRequirement; import com.qdesrame.openapi.diff.model.ChangedSecurityRequirements; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -16,6 +17,8 @@ import java.util.Optional; import java.util.stream.Collectors; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 07/01/18. */ @@ -72,7 +75,7 @@ private Pair getPair(SecurityScheme secu return new ImmutablePair<>(securityScheme.getType(), securityScheme.getIn()); } - protected Optional diff(List left, List right) { + protected Optional diff(List left, List right, DiffContext context) { left = left == null ? new ArrayList<>() : left; right = right == null ? new ArrayList<>() : getCopy(right); @@ -86,13 +89,13 @@ protected Optional diff(List l } else { SecurityRequirement rightSec = rightSecOpt.get(); right.remove(rightSec); - Optional diff = openApiDiff.getSecurityRequirementDiff().diff(leftSecurity, rightSec); + Optional diff = openApiDiff.getSecurityRequirementDiff().diff(leftSecurity, rightSec, context); diff.ifPresent(changedSecurityRequirements::addChanged); } } right.forEach(changedSecurityRequirements::addIncreased); - return changedSecurityRequirements.isDiff() ? Optional.of(changedSecurityRequirements) : Optional.empty(); + return isChanged(changedSecurityRequirements); } private List getCopy(List right) { diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/SecuritySchemeDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/SecuritySchemeDiff.java index de752a97c..57b09a33a 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/SecuritySchemeDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/SecuritySchemeDiff.java @@ -1,6 +1,7 @@ package com.qdesrame.openapi.diff.compare; import com.qdesrame.openapi.diff.model.ChangedSecurityScheme; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.model.ListDiff; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.security.SecurityScheme; @@ -10,6 +11,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + /** * Created by adarsh.sharma on 11/01/18. */ @@ -24,10 +27,10 @@ public SecuritySchemeDiff(OpenApiDiff openApiDiff) { this.rightComponents = openApiDiff.getNewSpecOpenApi() != null ? openApiDiff.getNewSpecOpenApi().getComponents() : null; } - public Optional diff(String leftSchemeRef, List leftScopes, String rightSchemeRef, List rightScopes) { + public Optional diff(String leftSchemeRef, List leftScopes, String rightSchemeRef, List rightScopes, DiffContext context) { SecurityScheme leftSecurityScheme = leftComponents.getSecuritySchemes().get(leftSchemeRef); SecurityScheme rightSecurityScheme = rightComponents.getSecuritySchemes().get(rightSchemeRef); - Optional changedSecuritySchemeOpt = cachedDiff(new HashSet<>(), leftSecurityScheme, rightSecurityScheme, leftSchemeRef, rightSchemeRef); + Optional changedSecuritySchemeOpt = cachedDiff(new HashSet<>(), leftSecurityScheme, rightSecurityScheme, leftSchemeRef, rightSchemeRef, context); ChangedSecurityScheme changedSecurityScheme = changedSecuritySchemeOpt.orElse(new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme)); changedSecurityScheme = getCopyWithoutScopes(changedSecurityScheme); @@ -38,11 +41,11 @@ public Optional diff(String leftSchemeRef, List l } } - return changedSecurityScheme.isDiff() ? Optional.of(changedSecurityScheme) : Optional.empty(); + return isChanged(changedSecurityScheme); } @Override - protected Optional computeDiff(HashSet refSet, SecurityScheme leftSecurityScheme, SecurityScheme rightSecurityScheme) { + protected Optional computeDiff(HashSet refSet, SecurityScheme leftSecurityScheme, SecurityScheme rightSecurityScheme, DiffContext context) { ChangedSecurityScheme changedSecurityScheme = new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme); changedSecurityScheme.setChangedDescription(!Objects.equals(leftSecurityScheme.getDescription(), rightSecurityScheme.getDescription())); diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ArraySchemaDiffResult.java b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ArraySchemaDiffResult.java index 222aa0a0a..02a7deec8 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ArraySchemaDiffResult.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ArraySchemaDiffResult.java @@ -2,6 +2,7 @@ import com.qdesrame.openapi.diff.compare.OpenApiDiff; import com.qdesrame.openapi.diff.model.ChangedSchema; +import com.qdesrame.openapi.diff.model.DiffContext; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; @@ -18,9 +19,9 @@ public ArraySchemaDiffResult(OpenApiDiff openApiDiff) { } @Override - public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right) { + public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right, DiffContext context) { ArraySchema leftArraySchema = (ArraySchema) left; ArraySchema rightArraySchema = (ArraySchema) right; - return openApiDiff.getSchemaDiff().diff(refSet, leftArraySchema.getItems(), rightArraySchema.getItems()); + return openApiDiff.getSchemaDiff().diff(refSet, leftArraySchema.getItems(), rightArraySchema.getItems(), context); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ComposedSchemaDiffResult.java b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ComposedSchemaDiffResult.java index 14e8e9ba8..a38247384 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ComposedSchemaDiffResult.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/ComposedSchemaDiffResult.java @@ -4,6 +4,7 @@ import com.qdesrame.openapi.diff.compare.OpenApiDiff; import com.qdesrame.openapi.diff.model.ChangedOneOfSchema; import com.qdesrame.openapi.diff.model.ChangedSchema; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.utils.RefPointer; import com.qdesrame.openapi.diff.utils.RefType; import io.swagger.v3.oas.models.Components; @@ -29,7 +30,7 @@ public ComposedSchemaDiffResult(OpenApiDiff openApiDiff) { } @Override - public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right) { + public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right, DiffContext context) { if(left instanceof ComposedSchema) { ComposedSchema leftComposedSchema = (ComposedSchema) left; ComposedSchema rightComposedSchema = (ComposedSchema) right; @@ -51,7 +52,7 @@ public Optional diff(HashSet refSet, Components leftCompo Map leftMapping = getMapping(leftComposedSchema); Map rightMapping = getMapping(rightComposedSchema); - ChangedOneOfSchema changedOneOfSchema = new ChangedOneOfSchema(leftMapping, rightMapping); + ChangedOneOfSchema changedOneOfSchema = new ChangedOneOfSchema(leftMapping, rightMapping, context); MapKeyDiff mappingDiff = MapKeyDiff.diff(leftMapping, rightMapping); changedOneOfSchema.setIncreasedMapping(mappingDiff.getIncreased()); changedOneOfSchema.setMissingMapping(mappingDiff.getMissing()); @@ -64,16 +65,14 @@ public Optional diff(HashSet refSet, Components leftCompo leftSchema.set$ref(leftMapping.get(key)); Schema rightSchema = new Schema(); rightSchema.set$ref(rightMapping.get(key)); - Optional changedSchema = openApiDiff.getSchemaDiff().diff(refSet, leftSchema, rightSchema); - if (changedSchema.isPresent() && changedSchema.get().isDiff()) { - changedMapping.put(key, changedSchema.get()); - } + Optional changedSchema = openApiDiff.getSchemaDiff().diff(refSet, leftSchema, rightSchema, context); + changedSchema.ifPresent(schema -> changedMapping.put(key, schema)); } changedSchema.setChangedOneOfSchema(changedOneOfSchema); } - return super.diff(refSet, leftComponents, rightComponents, left, right); + return super.diff(refSet, leftComponents, rightComponents, left, right, context); } else { - return openApiDiff.getSchemaDiff().getTypeChangedSchema(left, right); + return openApiDiff.getSchemaDiff().getTypeChangedSchema(left, right, context); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/SchemaDiffResult.java b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/SchemaDiffResult.java index d447e52c3..286a5a134 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/SchemaDiffResult.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/schemadiffresult/SchemaDiffResult.java @@ -3,6 +3,7 @@ import com.qdesrame.openapi.diff.compare.MapKeyDiff; import com.qdesrame.openapi.diff.compare.OpenApiDiff; import com.qdesrame.openapi.diff.model.ChangedSchema; +import com.qdesrame.openapi.diff.model.DiffContext; import com.qdesrame.openapi.diff.model.ListDiff; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.media.Schema; @@ -13,6 +14,8 @@ import java.util.Objects; import java.util.Optional; +import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged; + @Getter public class SchemaDiffResult { protected ChangedSchema changedSchema; @@ -28,7 +31,8 @@ public SchemaDiffResult(String type, OpenApiDiff openApiDiff) { this.changedSchema.setType(type); } - public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right) { + public Optional diff(HashSet refSet, Components leftComponents, Components rightComponents, Schema left, Schema right, DiffContext context) { + changedSchema.setContext(context); changedSchema.setOldSchema(left); changedSchema.setNewSchema(right); changedSchema.setChangeDeprecated(!Boolean.TRUE.equals(left.getDeprecated()) && Boolean.TRUE.equals(right.getDeprecated())); @@ -49,36 +53,33 @@ public Optional diff(HashSet refSet, Components leftCompo Map missingProp = propertyDiff.getMissing(); for (String key : propertyDiff.getSharedKey()) { - Optional resultSchema = openApiDiff.getSchemaDiff().diff(refSet, leftProperties.get(key), rightProperties.get(key)); - if (resultSchema.isPresent() && resultSchema.get().isDiff()) { - changedSchema.getChangedProperties().put(key, resultSchema.get()); - } + Optional resultSchema = openApiDiff.getSchemaDiff().diff(refSet, leftProperties.get(key), rightProperties.get(key), context); + resultSchema.ifPresent(changedSchema1 -> changedSchema.getChangedProperties().put(key, changedSchema1)); } - compareAdditionalProperties(refSet, left, right); + compareAdditionalProperties(refSet, left, right, context); changedSchema.getIncreasedProperties().putAll(increasedProp); changedSchema.getMissingProperties().putAll(missingProp); - return changedSchema.isDiff() ? Optional.of(changedSchema) : Optional.empty(); + return isChanged(changedSchema); } - private void compareAdditionalProperties(HashSet refSet, Schema leftSchema, Schema rightSchema) { + private void compareAdditionalProperties(HashSet refSet, Schema leftSchema, Schema rightSchema, DiffContext context) { Object left = leftSchema.getAdditionalProperties(); Object right = rightSchema.getAdditionalProperties(); if ((left != null && left instanceof Schema) || (right != null && right instanceof Schema)) { Schema leftAdditionalSchema = (Schema) left; Schema rightAdditionalSchema = (Schema) right; ChangedSchema apChangedSchema = new ChangedSchema(); + apChangedSchema.setContext(context); apChangedSchema.setOldSchema(leftAdditionalSchema); apChangedSchema.setNewSchema(rightAdditionalSchema); if (left != null && right != null) { Optional addPropChangedSchemaOP - = openApiDiff.getSchemaDiff().diff(refSet, leftAdditionalSchema, rightAdditionalSchema); + = openApiDiff.getSchemaDiff().diff(refSet, leftAdditionalSchema, rightAdditionalSchema, context); apChangedSchema = addPropChangedSchemaOP.orElse(apChangedSchema); } - if (apChangedSchema.isDiff()) { - changedSchema.setAddPropChangedSchema(apChangedSchema); - } + isChanged(apChangedSchema).ifPresent(changedSchema::setAddPropChangedSchema); } } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/Changed.java b/src/main/java/com/qdesrame/openapi/diff/model/Changed.java index 8922201e1..70aa8b9ce 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/Changed.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/Changed.java @@ -1,7 +1,21 @@ package com.qdesrame.openapi.diff.model; public interface Changed { - boolean isDiff(); + DiffResult isChanged(); - boolean isDiffBackwardCompatible(); + default boolean isCompatible() { + return isChanged().isCompatible(); + } + + default boolean isIncompatible() { + return isChanged().isIncompatible(); + } + + default boolean isUnchanged() { + return isChanged().isUnchanged(); + } + + default boolean isDifferent() { + return isChanged().isDifferent(); + } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedApiResponse.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedApiResponse.java index 5d2b2e937..1d98d358d 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedApiResponse.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedApiResponse.java @@ -14,28 +14,30 @@ @Getter @Setter public class ChangedApiResponse implements Changed { - private ApiResponses oldApiResponses; - private ApiResponses newApiResponses; + private final ApiResponses oldApiResponses; + private final ApiResponses newApiResponses; + private final DiffContext context; private Map missingResponses; private Map addResponses; private Map changedResponses; - public ChangedApiResponse(ApiResponses oldApiResponses, ApiResponses newApiResponses) { + public ChangedApiResponse(ApiResponses oldApiResponses, ApiResponses newApiResponses, DiffContext context) { this.oldApiResponses = oldApiResponses; this.newApiResponses = newApiResponses; + this.context = context; this.missingResponses = new HashMap<>(); this.addResponses = new HashMap<>(); this.changedResponses = new HashMap<>(); } @Override - public boolean isDiff() { - return !addResponses.isEmpty() || !missingResponses.isEmpty() || !changedResponses.isEmpty(); - } - - @Override - public boolean isDiffBackwardCompatible() { - return addResponses.size() == 0 - && changedResponses.values().stream().allMatch(c -> c.isDiffBackwardCompatible()); + public DiffResult isChanged() { + if (addResponses.size() == 0 && missingResponses.size() == 0 && changedResponses.size() == 0) { + return DiffResult.NO_CHANGES; + } + if (missingResponses.size() == 0 && changedResponses.values().stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedContent.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedContent.java index 2228fe425..fcdb1a9ed 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedContent.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedContent.java @@ -13,31 +13,34 @@ */ @Getter @Setter -public class ChangedContent implements RequestResponseChanged { - private Content oldContent; - private Content newContent; +public class ChangedContent implements Changed { + private final Content oldContent; + private final Content newContent; + private final DiffContext context; private Map increased; private Map missing; private Map changed; - public ChangedContent(Content oldContent, Content newContent) { + public ChangedContent(Content oldContent, Content newContent, DiffContext context) { this.oldContent = oldContent; this.newContent = newContent; + this.context = context; this.increased = new HashMap<>(); this.missing = new HashMap<>(); this.changed = new HashMap<>(); } @Override - public boolean isDiff() { - return !increased.isEmpty() || !missing.isEmpty() || !changed.isEmpty(); - } - - @Override - public boolean isDiffBackwardCompatible(boolean isRequest) { - return ((isRequest && missing.isEmpty()) || (!isRequest && increased.isEmpty())) - && changed.values().stream().allMatch(c -> c.isDiffBackwardCompatible(isRequest)); + public DiffResult isChanged() { + if (increased.isEmpty() && missing.isEmpty() && changed.isEmpty()) { + return DiffResult.NO_CHANGES; + } + if (((context.isRequest() && missing.isEmpty()) || (context.isResponse() && increased.isEmpty())) + && changed.values().stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeader.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeader.java index a8d1124d7..09ebf99de 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeader.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeader.java @@ -10,8 +10,9 @@ @Getter @Setter public class ChangedHeader implements Changed { - private Header oldHeader; - private Header newHeader; + private final Header oldHeader; + private final Header newHeader; + private final DiffContext context; private boolean changeDescription; private boolean changeRequired; @@ -21,28 +22,25 @@ public class ChangedHeader implements Changed { private ChangedSchema changedSchema; private ChangedContent changedContent; - public ChangedHeader(Header oldHeader, Header newHeader) { + public ChangedHeader(Header oldHeader, Header newHeader, DiffContext context) { this.oldHeader = oldHeader; this.newHeader = newHeader; + this.context = context; } @Override - public boolean isDiff() { - return changeDescription - || changeRequired - || changeDeprecated - || changeStyle - || changeExplode - || (changedSchema != null && changedSchema.isDiff()) - || (changedContent != null && changedContent.isDiff()); + public DiffResult isChanged() { + if (!changeDescription && !changeRequired && !changeDeprecated && !changeStyle && !changeExplode + && (changedSchema == null || changedSchema.isUnchanged()) + && (changedContent == null || changedContent.isUnchanged())) { + return DiffResult.NO_CHANGES; + } + if (!changeRequired && !changeStyle && !changeExplode + && (changedSchema == null || changedSchema.isCompatible()) + && (changedContent == null || changedContent.isCompatible())) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } - @Override - public boolean isDiffBackwardCompatible() { - return changeRequired - && changeStyle - && changeExplode - && (changedSchema == null || changedSchema.isDiffBackwardCompatible(false)) - && (changedContent == null || changedContent.isDiffBackwardCompatible(false)); - } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeaders.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeaders.java index 60eb461fd..7824e9d14 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeaders.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedHeaders.java @@ -12,28 +12,28 @@ @Getter @Setter public class ChangedHeaders implements Changed { - private Map oldHeaders; - private Map newHeaders; + private final Map oldHeaders; + private final Map newHeaders; + private final DiffContext context; private Map increased; private Map missing; private Map changed; - public ChangedHeaders(Map oldHeaders, Map newHeaders) { + public ChangedHeaders(Map oldHeaders, Map newHeaders, DiffContext context) { this.oldHeaders = oldHeaders; this.newHeaders = newHeaders; + this.context = context; } @Override - public boolean isDiff() { - return !increased.isEmpty() - || !missing.isEmpty() - || (changed != null && !changed.isEmpty()); - } - - @Override - public boolean isDiffBackwardCompatible() { - return missing.isEmpty() - && (changed == null || changed.values().stream().allMatch(c -> c.isDiffBackwardCompatible())); + public DiffResult isChanged() { + if (increased.isEmpty() && missing.isEmpty() && (changed == null || changed.isEmpty())) { + return DiffResult.NO_CHANGES; + } + if (missing.isEmpty() && (changed == null || changed.values().stream().allMatch(Changed::isCompatible))) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedMediaType.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedMediaType.java index d06f7e0ab..3182182b2 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedMediaType.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedMediaType.java @@ -6,24 +6,27 @@ @Getter @Setter -public class ChangedMediaType implements RequestResponseChanged { - private Schema oldSchema; - private Schema newSchema; +public class ChangedMediaType implements Changed { + private final Schema oldSchema; + private final Schema newSchema; + private final DiffContext context; private ChangedSchema changedSchema; - public ChangedMediaType(Schema oldSchema, Schema newSchema) { + public ChangedMediaType(Schema oldSchema, Schema newSchema, DiffContext context) { this.oldSchema = oldSchema; this.newSchema = newSchema; + this.context = context; } @Override - public boolean isDiff() { - return (changedSchema != null && changedSchema.isDiff()); - } - - @Override - public boolean isDiffBackwardCompatible(boolean isRequest) { - return (changedSchema == null || changedSchema.isDiffBackwardCompatible(isRequest)); + public DiffResult isChanged() { + if (this.changedSchema == null || this.changedSchema.isUnchanged()) { + return DiffResult.NO_CHANGES; + } + if (this.changedSchema.isCompatible()) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlow.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlow.java index 5469d9f4f..9c8c15acb 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlow.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlow.java @@ -23,16 +23,11 @@ public ChangedOAuthFlow(OAuthFlow oldOAuthFlow, OAuthFlow newOAuthFlow) { } @Override - public boolean isDiff() { - return changedAuthorizationUrl || - changedTokenUrl || - changedRefreshUrl; - } - - @Override - public boolean isDiffBackwardCompatible() { - return !changedAuthorizationUrl && - !changedTokenUrl && - !changedRefreshUrl; + public DiffResult isChanged() { + if (!changedAuthorizationUrl && !changedTokenUrl && !changedRefreshUrl) { + return DiffResult.NO_CHANGES; + } else { + return DiffResult.INCOMPATIBLE; + } } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlows.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlows.java index 39f48a428..2c6a8a2b8 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlows.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOAuthFlows.java @@ -10,8 +10,8 @@ @Getter @Setter public class ChangedOAuthFlows implements Changed { - private OAuthFlows oldOAuthFlows; - private OAuthFlows newOAuthFlows; + private final OAuthFlows oldOAuthFlows; + private final OAuthFlows newOAuthFlows; private ChangedOAuthFlow changedImplicitOAuthFlow; private ChangedOAuthFlow changedPasswordOAuthFlow; @@ -24,18 +24,20 @@ public ChangedOAuthFlows(OAuthFlows oldOAuthFlows, OAuthFlows newOAuthFlows) { } @Override - public boolean isDiff() { - return (changedImplicitOAuthFlow != null && changedImplicitOAuthFlow.isDiff()) || - (changedPasswordOAuthFlow != null && changedPasswordOAuthFlow.isDiff()) || - (changedClientCredentialOAuthFlow != null && changedClientCredentialOAuthFlow.isDiff()) || - (changedAuthorizationCodeOAuthFlow != null && changedAuthorizationCodeOAuthFlow.isDiff()); + public DiffResult isChanged() { + if ((changedImplicitOAuthFlow == null || changedImplicitOAuthFlow.isUnchanged()) + && (changedPasswordOAuthFlow == null || changedPasswordOAuthFlow.isUnchanged()) + && (changedClientCredentialOAuthFlow == null || changedClientCredentialOAuthFlow.isUnchanged()) + && (changedAuthorizationCodeOAuthFlow == null || changedAuthorizationCodeOAuthFlow.isUnchanged())) { + return DiffResult.NO_CHANGES; + } + if ((changedImplicitOAuthFlow == null || changedImplicitOAuthFlow.isCompatible()) + && (changedPasswordOAuthFlow == null || changedPasswordOAuthFlow.isCompatible()) + && (changedClientCredentialOAuthFlow == null || changedClientCredentialOAuthFlow.isCompatible()) + && (changedAuthorizationCodeOAuthFlow == null || changedAuthorizationCodeOAuthFlow.isCompatible())) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } - @Override - public boolean isDiffBackwardCompatible() { - return (changedImplicitOAuthFlow == null || changedImplicitOAuthFlow.isDiffBackwardCompatible()) && - (changedPasswordOAuthFlow == null || changedPasswordOAuthFlow.isDiffBackwardCompatible()) && - (changedClientCredentialOAuthFlow == null || changedClientCredentialOAuthFlow.isDiffBackwardCompatible()) && - (changedAuthorizationCodeOAuthFlow == null || changedAuthorizationCodeOAuthFlow.isDiffBackwardCompatible()); - } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOneOfSchema.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOneOfSchema.java index 7136cdaf6..56b0da2c2 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOneOfSchema.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOneOfSchema.java @@ -10,27 +10,30 @@ */ @Getter @Setter -public class ChangedOneOfSchema implements RequestResponseChanged { - private Map oldMapping; - private Map newMapping; +public class ChangedOneOfSchema implements Changed { + private final Map oldMapping; + private final Map newMapping; + private final DiffContext context; private Map increasedMapping; private Map missingMapping; private Map changedMapping; - public ChangedOneOfSchema(Map oldMapping, Map newMapping) { + public ChangedOneOfSchema(Map oldMapping, Map newMapping, DiffContext context) { this.oldMapping = oldMapping; this.newMapping = newMapping; + this.context = context; } @Override - public boolean isDiff() { - return increasedMapping.size() > 0 || missingMapping.size() > 0 || changedMapping.size() > 0; - } - - @Override - public boolean isDiffBackwardCompatible(boolean isRequest) { - return ((isRequest && missingMapping.isEmpty()) || (!isRequest && increasedMapping.isEmpty())) - && changedMapping.values().stream().allMatch(m -> m.isDiffBackwardCompatible(isRequest)); + public DiffResult isChanged() { + if (increasedMapping.size() == 0 && missingMapping.size() == 0 && changedMapping.size() == 0) { + return DiffResult.NO_CHANGES; + } + if (((context.isRequest() && missingMapping.isEmpty()) || (context.isResponse() && increasedMapping.isEmpty())) + && changedMapping.values().stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOpenApi.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOpenApi.java index b2625bc0f..14f00d9c0 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOpenApi.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOpenApi.java @@ -23,21 +23,20 @@ public class ChangedOpenApi implements Changed { public List getDeprecatedEndpoints() { return changedOperations.stream() - .filter(c -> c.isDeprecated()) + .filter(ChangedOperation::isDeprecated) .map(c -> EndpointUtils.convert2Endpoint(c.getPathUrl(), c.getHttpMethod(), c.getNewOperation())) .collect(Collectors.toList()); } @Override - public boolean isDiff() { - return newEndpoints.size() > 0 - || missingEndpoints.size() > 0 - || changedOperations.size() > 0; - } - - public boolean isDiffBackwardCompatible() { - return missingEndpoints.size() == 0 - && changedOperations.stream().allMatch(c -> c.isDiffBackwardCompatible()); + public DiffResult isChanged() { + if (newEndpoints.size() == 0 && missingEndpoints.size() == 0 && changedOperations.size() == 0) { + return DiffResult.NO_CHANGES; + } + if (missingEndpoints.size() == 0 && changedOperations.stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOperation.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOperation.java index 96bb345a6..a5d7d4fd2 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedOperation.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedOperation.java @@ -27,31 +27,32 @@ public ChangedOperation(String pathUrl, PathItem.HttpMethod httpMethod, Operatio } @Override - public boolean isDiff() { - return deprecated || isDiffParam() || isDiffRequest() || isDiffResponse() || isDiffSecurity(); + public DiffResult isChanged() { + //TODO BETTER HANDLING FOR DEPRECIATION + if (!deprecated && isChangedParam().isUnchanged() && isChangedRequest().isUnchanged() + && isChangedResponse().isUnchanged() && isChangedSecurity().isUnchanged()) { + return DiffResult.NO_CHANGES; + } + if (isChangedParam().isCompatible() && isChangedRequest().isCompatible() + && isChangedResponse().isCompatible() && isChangedSecurity().isCompatible()) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } - @Override - public boolean isDiffBackwardCompatible() { - return (changedParameters == null || changedParameters.isDiffBackwardCompatible()) - && (changedRequestBody == null || changedRequestBody.isDiffBackwardCompatible()) - && (changedApiResponse == null || changedApiResponse.isDiffBackwardCompatible()) - && (changedSecurityRequirements == null || changedSecurityRequirements.isDiffBackwardCompatible()); - } - - public boolean isDiffParam() { - return changedParameters != null && changedParameters.isDiff(); + public DiffResult isChangedParam() { + return changedParameters == null ? DiffResult.NO_CHANGES : changedParameters.isChanged(); } - public boolean isDiffResponse() { - return changedApiResponse != null && changedApiResponse.isDiff(); + public DiffResult isChangedResponse() { + return changedApiResponse == null ? DiffResult.NO_CHANGES : changedApiResponse.isChanged(); } - public boolean isDiffRequest() { - return changedRequestBody != null && changedRequestBody.isDiff(); + public DiffResult isChangedRequest() { + return changedRequestBody == null ? DiffResult.NO_CHANGES : changedRequestBody.isChanged(); } - public boolean isDiffSecurity() { - return changedSecurityRequirements != null && changedSecurityRequirements.isDiff(); + public DiffResult isChangedSecurity() { + return changedSecurityRequirements == null ? DiffResult.NO_CHANGES : changedSecurityRequirements.isChanged(); } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameter.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameter.java index 29972fc6c..72303d1e0 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameter.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameter.java @@ -12,6 +12,7 @@ public class ChangedParameter implements Changed { private String name; private String in; + private final DiffContext context; private boolean changeDescription; private boolean changeRequired; @@ -22,30 +23,32 @@ public class ChangedParameter implements Changed { private ChangedSchema changedSchema; private ChangedContent changedContent; - public ChangedParameter(String name, String in) { + public ChangedParameter(String name, String in, DiffContext context) { this.name = name; this.in = in; + this.context = context; } @Override - public boolean isDiff() { - return changeDescription - || changeRequired - || deprecated - || changeAllowEmptyValue - || changeStyle - || changeExplode - || (changedSchema != null && changedSchema.isDiff()) - || (changedContent != null && changedContent.isDiff()); - } - - @Override - public boolean isDiffBackwardCompatible() { - return (!changeRequired || Boolean.TRUE.equals(oldParameter.getRequired())) + public DiffResult isChanged() { + if (!changeDescription + && !changeRequired + && !deprecated + && !changeAllowEmptyValue + && !changeStyle + && !changeExplode + && (changedSchema == null || changedSchema.isUnchanged()) + && (changedContent == null || changedContent.isUnchanged())) { + return DiffResult.NO_CHANGES; + } + if ((!changeRequired || Boolean.TRUE.equals(oldParameter.getRequired())) && (!changeAllowEmptyValue || Boolean.TRUE.equals(newParameter.getAllowEmptyValue())) && !changeStyle && !changeExplode - && (changedSchema == null || changedSchema.isDiffBackwardCompatible(true)) - && (changedContent == null || changedContent.isDiffBackwardCompatible(true)); + && (changedSchema == null || changedSchema.isCompatible()) + && (changedContent == null || changedContent.isCompatible())) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameters.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameters.java index e4054a589..bc8d10766 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameters.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedParameters.java @@ -10,29 +10,32 @@ @Getter @Setter public class ChangedParameters implements Changed { - private List oldParameterList; - private List newParameterList; + private final List oldParameterList; + private final List newParameterList; + private final DiffContext context; private List increased; private List missing; private List changed; - public ChangedParameters(List oldParameterList, List newParameterList) { + public ChangedParameters(List oldParameterList, List newParameterList, DiffContext context) { this.oldParameterList = oldParameterList; this.newParameterList = newParameterList; + this.context = context; this.increased = new ArrayList<>(); this.missing = new ArrayList<>(); this.changed = new ArrayList<>(); } @Override - public boolean isDiff() { - return !increased.isEmpty() || !missing.isEmpty() || !changed.isEmpty(); - } - - @Override - public boolean isDiffBackwardCompatible() { - return increased.stream().noneMatch(Parameter::getRequired) && missing.isEmpty() - && changed.stream().allMatch(ChangedParameter::isDiffBackwardCompatible); + public DiffResult isChanged() { + if (increased.isEmpty() && missing.isEmpty() && changed.isEmpty()) { + return DiffResult.NO_CHANGES; + } + if (increased.stream().noneMatch(Parameter::getRequired) && missing.isEmpty() + && changed.stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedPath.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedPath.java index 7b44c0b1d..fd1fc0c82 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedPath.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedPath.java @@ -13,29 +13,33 @@ @Getter @Setter public class ChangedPath implements Changed { + private final String pathUrl; + private final PathItem oldPath; + private final PathItem newPath; + private final DiffContext context; + Map increased; Map missing; List changed; - private String pathUrl; - private PathItem oldPath; - private PathItem newPath; - public ChangedPath(String pathUrl, PathItem oldPath, PathItem newPath) { + public ChangedPath(String pathUrl, PathItem oldPath, PathItem newPath, DiffContext context) { this.pathUrl = pathUrl; this.oldPath = oldPath; this.newPath = newPath; + this.context = context; this.increased = new LinkedHashMap<>(); this.missing = new LinkedHashMap<>(); this.changed = new ArrayList<>(); } @Override - public boolean isDiff() { - return !increased.isEmpty() || !missing.isEmpty() || !changed.isEmpty(); - } - - @Override - public boolean isDiffBackwardCompatible() { - return missing.isEmpty() && changed.stream().allMatch(ChangedOperation::isDiffBackwardCompatible); + public DiffResult isChanged() { + if (increased.isEmpty() && missing.isEmpty() && changed.isEmpty()) { + return DiffResult.NO_CHANGES; + } + if (missing.isEmpty() && changed.stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedPaths.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedPaths.java index 6ee8357d9..4fa4a83c2 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedPaths.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedPaths.java @@ -10,8 +10,8 @@ @Getter @Setter public class ChangedPaths implements Changed { - private Map oldPathMap; - private Map newPathMap; + private final Map oldPathMap; + private final Map newPathMap; private Map increased; private Map missing; @@ -26,12 +26,13 @@ public ChangedPaths(Map oldPathMap, Map newP } @Override - public boolean isDiff() { - return !increased.isEmpty() || !missing.isEmpty() || !changed.isEmpty(); - } - - @Override - public boolean isDiffBackwardCompatible() { - return missing.isEmpty() && changed.values().stream().allMatch(ChangedPath::isDiffBackwardCompatible); + public DiffResult isChanged() { + if (increased.isEmpty() && missing.isEmpty() && changed.isEmpty()) { + return DiffResult.NO_CHANGES; + } + if (missing.isEmpty() && changed.values().stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedRequestBody.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedRequestBody.java index 2e7618eb5..cf481cd72 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedRequestBody.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedRequestBody.java @@ -10,24 +10,28 @@ @Getter @Setter public class ChangedRequestBody implements Changed { - private RequestBody oldRequestBody; - private RequestBody newRequestBody; + private final RequestBody oldRequestBody; + private final RequestBody newRequestBody; + private final DiffContext context; + private boolean changeDescription; private boolean changeRequired; private ChangedContent changedContent; - public ChangedRequestBody(RequestBody oldRequestBody, RequestBody newRequestBody) { + public ChangedRequestBody(RequestBody oldRequestBody, RequestBody newRequestBody, DiffContext context) { this.oldRequestBody = oldRequestBody; this.newRequestBody = newRequestBody; + this.context = context; } @Override - public boolean isDiff() { - return changeDescription || changeRequired || (changedContent != null && changedContent.isDiff()); - } - - @Override - public boolean isDiffBackwardCompatible() { - return !changeRequired && (changedContent == null || changedContent.isDiffBackwardCompatible(true)); + public DiffResult isChanged() { + if (!changeDescription && !changeRequired && (changedContent == null || changedContent.isUnchanged())) { + return DiffResult.NO_CHANGES; + } + if (!changeRequired && (changedContent == null || changedContent.isCompatible())) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedResponse.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedResponse.java index 762e9fb88..f4805d1b6 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedResponse.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedResponse.java @@ -1,5 +1,6 @@ package com.qdesrame.openapi.diff.model; +import com.qdesrame.openapi.diff.utils.ChangedUtils; import io.swagger.v3.oas.models.responses.ApiResponse; import lombok.Getter; import lombok.Setter; @@ -7,28 +8,28 @@ @Getter @Setter public class ChangedResponse implements Changed { - private ApiResponse oldApiResponse; - private ApiResponse newApiResponse; + private final ApiResponse oldApiResponse; + private final ApiResponse newApiResponse; + private final DiffContext context; private boolean changeDescription; private ChangedHeaders changedHeaders; private ChangedContent changedContent; - public ChangedResponse(ApiResponse oldApiResponse, ApiResponse newApiResponse) { + public ChangedResponse(ApiResponse oldApiResponse, ApiResponse newApiResponse, DiffContext context) { this.oldApiResponse = oldApiResponse; this.newApiResponse = newApiResponse; + this.context = context; } @Override - public boolean isDiff() { - return changeDescription - ||(changedContent != null && changedContent.isDiff()) - || (changedHeaders != null && changedHeaders.isDiff()); - } - - @Override - public boolean isDiffBackwardCompatible() { - return (changedContent == null || changedContent.isDiffBackwardCompatible(false)) - && (changedHeaders == null || changedHeaders.isDiffBackwardCompatible()); + public DiffResult isChanged() { + if (!changeDescription && ChangedUtils.isUnchanged(changedContent) && ChangedUtils.isUnchanged(changedHeaders)) { + return DiffResult.NO_CHANGES; + } + if (ChangedUtils.isCompatible(changedContent) && ChangedUtils.isCompatible(changedHeaders)) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSchema.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSchema.java index 2c74f05e8..b9c91e6a2 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSchema.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSchema.java @@ -1,5 +1,6 @@ package com.qdesrame.openapi.diff.model; +import com.qdesrame.openapi.diff.utils.ChangedUtils; import io.swagger.v3.oas.models.media.Schema; import lombok.Getter; import lombok.Setter; @@ -13,7 +14,8 @@ */ @Getter @Setter -public class ChangedSchema implements RequestResponseChanged { +public class ChangedSchema implements Changed { + protected DiffContext context; protected Schema oldSchema; protected Schema newSchema; protected String type; @@ -42,33 +44,21 @@ public ChangedSchema() { } @Override - public boolean isDiff() { - return Boolean.TRUE.equals(changedType) - || (oldSchema != null && newSchema == null) - || (oldSchema == null && newSchema != null) - || changeWriteOnly - || changedMaxLength - || changeReadOnly - || (changeEnum != null && (changeEnum.getIncreased().size() > 0 || changeEnum.getMissing().size() > 0)) - || changeFormat - || increasedProperties.size() > 0 - || missingProperties.size() > 0 - || changedProperties.size() > 0 - || changeDeprecated - || (changeRequired != null && changeRequired.getIncreased().size() > 0) - || (changeRequired != null && changeRequired.getMissing().size() > 0) - || discriminatorPropertyChanged - || (addPropChangedSchema != null) - || (changedOneOfSchema != null && changedOneOfSchema.isDiff()); - } - - @Override - public boolean isDiffBackwardCompatible(boolean isRequest) { + public DiffResult isChanged() { + if (!changedType && (oldSchema == null && newSchema == null || oldSchema != null && newSchema != null) + && !changeWriteOnly && !changedMaxLength && !changeReadOnly + && (changeEnum == null || changeEnum.isUnchanged()) + && !changeFormat && increasedProperties.size() == 0 && missingProperties.size() == 0 + && changedProperties.values().size() == 0 && !changeDeprecated + && (changeRequired == null || changeRequired.isUnchanged()) && !discriminatorPropertyChanged + && ChangedUtils.isUnchanged(addPropChangedSchema) && ChangedUtils.isUnchanged(changedOneOfSchema)) { + return DiffResult.NO_CHANGES; + } boolean backwardCompatibleForRequest = (changeEnum == null || changeEnum.getMissing().isEmpty()) && (changeRequired == null || CollectionUtils.isEmpty(changeRequired.getIncreased())) && (oldSchema != null || newSchema == null) && (!changedMaxLength || newSchema.getMaxLength() == null || - (oldSchema.getMaxLength() != null && oldSchema.getMaxLength()<= newSchema.getMaxLength())); + (oldSchema.getMaxLength() != null && oldSchema.getMaxLength() <= newSchema.getMaxLength())); boolean backwardCompatibleForResponse = (changeEnum == null || changeEnum.getIncreased().isEmpty()) && missingProperties.isEmpty() && @@ -76,11 +66,13 @@ public boolean isDiffBackwardCompatible(boolean isRequest) { (!changedMaxLength || oldSchema.getMaxLength() == null || (newSchema.getMaxLength() != null && newSchema.getMaxLength() <= oldSchema.getMaxLength())); - return (isRequest && backwardCompatibleForRequest || !isRequest && backwardCompatibleForResponse ) - && !changedType - && !discriminatorPropertyChanged - && (changedOneOfSchema == null || changedOneOfSchema.isDiffBackwardCompatible(isRequest)) - && (addPropChangedSchema == null || addPropChangedSchema.isDiffBackwardCompatible(isRequest)) - && changedProperties.values().stream().allMatch(p -> p.isDiffBackwardCompatible(isRequest)); + if ((context.isRequest() && backwardCompatibleForRequest || context.isResponse() && backwardCompatibleForResponse) + && !changedType && !discriminatorPropertyChanged && ChangedUtils.isCompatible(changedOneOfSchema) + && ChangedUtils.isCompatible(addPropChangedSchema) + && changedProperties.values().stream().allMatch(Changed::isCompatible)) { + return DiffResult.COMPATIBLE; + } + + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirement.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirement.java index d14defa2f..71773808c 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirement.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirement.java @@ -27,32 +27,32 @@ public ChangedSecurityRequirement(SecurityRequirement oldSecurityRequirement, Se } @Override - public boolean isDiff() { - return missing != null || increased != null || CollectionUtils.isNotEmpty(changed); - } - - @Override - public boolean isDiffBackwardCompatible() { - return increased == null && - (changed == null || changed.stream().allMatch(x -> x.isDiffBackwardCompatible())); + public DiffResult isChanged() { + if (missing == null && increased == null && CollectionUtils.isEmpty(changed)) { + return DiffResult.NO_CHANGES; + } + if (increased == null && (changed == null || changed.stream().allMatch(Changed::isCompatible))) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } public void addMissing(String key, List scopes) { - if(missing == null) { + if (missing == null) { missing = new SecurityRequirement(); } missing.put(key, scopes); } public void addIncreased(String key, List scopes) { - if(increased == null) { + if (increased == null) { increased = new SecurityRequirement(); } increased.put(key, scopes); } public void addChanged(ChangedSecurityScheme changedSecurityScheme) { - if(changed == null) { + if (changed == null) { changed = new ArrayList<>(); } changed.add(changedSecurityScheme); diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirements.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirements.java index b1353291c..d18f22e29 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirements.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityRequirements.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.models.security.SecurityRequirement; import lombok.Getter; import lombok.Setter; +import org.apache.commons.collections4.CollectionUtils; import java.util.ArrayList; import java.util.List; @@ -27,16 +28,14 @@ public ChangedSecurityRequirements(List oldSecurityRequirem } @Override - public boolean isDiff() { - return (missing != null && !missing.isEmpty()) || - (increased != null && !increased.isEmpty()) || - (changed != null && changed.stream().anyMatch(x -> x.isDiff())); - } - - @Override - public boolean isDiffBackwardCompatible() { - return (missing == null || missing.isEmpty()) && - (changed == null || changed.stream().allMatch(x -> x.isDiffBackwardCompatible())); + public DiffResult isChanged() { + if (CollectionUtils.isEmpty(missing) && CollectionUtils.isEmpty(increased) && CollectionUtils.isEmpty(changed)) { + return DiffResult.NO_CHANGES; + } + if (CollectionUtils.isEmpty(missing) && (changed == null || changed.stream().allMatch(Changed::isCompatible))) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } public void addMissing(SecurityRequirement securityRequirement) { diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityScheme.java b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityScheme.java index 75387afcb..068430866 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityScheme.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ChangedSecurityScheme.java @@ -1,5 +1,6 @@ package com.qdesrame.openapi.diff.model; +import com.qdesrame.openapi.diff.utils.ChangedUtils; import io.swagger.v3.oas.models.security.SecurityScheme; import lombok.Getter; import lombok.Setter; @@ -27,25 +28,17 @@ public ChangedSecurityScheme(SecurityScheme oldSecurityScheme, SecurityScheme ne } @Override - public boolean isDiff() { - return changedType || - changedDescription || - changedIn || - changedScheme || - changedBearerFormat || - (changedOAuthFlows != null && changedOAuthFlows.isDiff()) || - changedOpenIdConnectUrl || - changedScopes != null; - } - - @Override - public boolean isDiffBackwardCompatible() { - return !changedType && - !changedIn && - !changedScheme && - !changedBearerFormat && - (changedOAuthFlows == null || changedOAuthFlows.isDiffBackwardCompatible()) && - !changedOpenIdConnectUrl && - (changedScopes == null || changedScopes.getIncreased().isEmpty()); + public DiffResult isChanged() { + if (!changedType && !changedDescription && !changedIn && !changedScheme && !changedBearerFormat + && ChangedUtils.isUnchanged(changedOAuthFlows) && !changedOpenIdConnectUrl + && (changedScopes == null || changedScopes.isUnchanged())) { + return DiffResult.NO_CHANGES; + } + if (!changedType && !changedIn && !changedScheme && !changedBearerFormat + && ChangedUtils.isCompatible(changedOAuthFlows) && !changedOpenIdConnectUrl + && (changedScopes == null || changedScopes.getIncreased().isEmpty())) { + return DiffResult.COMPATIBLE; + } + return DiffResult.INCOMPATIBLE; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java new file mode 100644 index 000000000..4e0ede11b --- /dev/null +++ b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java @@ -0,0 +1,21 @@ +package com.qdesrame.openapi.diff.model; + +import io.swagger.v3.oas.models.PathItem; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +/** + * Created by Quentin Desramé on 04/04/17. + */ +@Getter +@Setter +public class DiffContext { + + private String url; + private Map parameters; + private PathItem.HttpMethod method; + private boolean response; + private boolean request; +} diff --git a/src/main/java/com/qdesrame/openapi/diff/model/DiffResult.java b/src/main/java/com/qdesrame/openapi/diff/model/DiffResult.java new file mode 100644 index 000000000..f9ece2754 --- /dev/null +++ b/src/main/java/com/qdesrame/openapi/diff/model/DiffResult.java @@ -0,0 +1,34 @@ +package com.qdesrame.openapi.diff.model; + +public enum DiffResult { + NO_CHANGES("no_changes"), + COMPATIBLE("compatible"), + INCOMPATIBLE("incompatible"), + UNKNOWN("unknown"); + + private final String value; + + DiffResult(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public boolean isUnchanged() { + return this.equals(NO_CHANGES); + } + + public boolean isDifferent() { + return !this.equals(NO_CHANGES); + } + + public boolean isIncompatible() { + return !this.equals(NO_CHANGES) && !this.equals(COMPATIBLE); + } + + public boolean isCompatible() { + return this.equals(NO_CHANGES) || this.equals(COMPATIBLE); + } +} diff --git a/src/main/java/com/qdesrame/openapi/diff/model/ListDiff.java b/src/main/java/com/qdesrame/openapi/diff/model/ListDiff.java index 701944f0f..d6faab83a 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/ListDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/ListDiff.java @@ -44,4 +44,8 @@ public static ListDiff diff(List left, List right) { return instance; } + public boolean isUnchanged() { + return missing.size() == 0 && increased.size() == 0; + } + } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/RequestResponseChanged.java b/src/main/java/com/qdesrame/openapi/diff/model/RequestResponseChanged.java deleted file mode 100644 index b6b0786ab..000000000 --- a/src/main/java/com/qdesrame/openapi/diff/model/RequestResponseChanged.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.qdesrame.openapi.diff.model; - -/** - * Created by adarsh.sharma on 24/12/17. - */ -public interface RequestResponseChanged { - boolean isDiff(); - boolean isDiffBackwardCompatible(boolean isRequest); -} diff --git a/src/main/java/com/qdesrame/openapi/diff/output/ConsoleRender.java b/src/main/java/com/qdesrame/openapi/diff/output/ConsoleRender.java index 45c391a57..2abcb5ffc 100644 --- a/src/main/java/com/qdesrame/openapi/diff/output/ConsoleRender.java +++ b/src/main/java/com/qdesrame/openapi/diff/output/ConsoleRender.java @@ -17,7 +17,7 @@ public class ConsoleRender implements Render { @Override public String render(ChangedOpenApi diff) { output = new StringBuilder(); - if (!diff.isDiff()) { + if (diff.isUnchanged()) { output.append("No differences. Specifications are equivalents"); } else { output.append(bigTitle("Api Change Log")) @@ -39,7 +39,7 @@ public String render(ChangedOpenApi diff) { output .append(renderBody(ol_newEndpoint, ol_missingEndpoint, ol_deprecatedEndpoint, ol_changed)) .append(title("Result")) - .append(StringUtils.center(diff.isDiffBackwardCompatible() ? + .append(StringUtils.center(diff.isCompatible() ? "API changes are backward compatible" : "API changes broke backward compatibility", LINE_LENGTH)) .append(System.lineSeparator()) .append(separator('-')); @@ -57,17 +57,17 @@ private String ol_changed(List operations) { String desc = operation.getSummary(); StringBuilder ul_detail = new StringBuilder(); - if (operation.isDiffParam()) { + if (operation.isChangedParam().isDifferent()) { ul_detail.append(StringUtils.repeat(' ', 2)).append("Parameter:") .append(System.lineSeparator()) .append(ul_param(operation.getChangedParameters())); } - if (operation.isDiffRequest()) { + if (operation.isChangedRequest().isDifferent()) { ul_detail.append(StringUtils.repeat(' ', 2)).append("Request:") .append(System.lineSeparator()) .append(ul_content(operation.getChangedRequestBody().getChangedContent(), true)); } - if (operation.isDiffResponse()) { + if (operation.isChangedResponse().isDifferent()) { ul_detail.append(StringUtils.repeat(' ', 2)).append("Return Type:") .append(System.lineSeparator()) .append(ul_response(operation.getChangedApiResponse())); @@ -142,8 +142,7 @@ private String itemContent(String title, String contentType, ChangedMediaType ch sb.append(itemContent(title, contentType)) .append(StringUtils.repeat(' ', 10)) .append("Schema: ") - .append(changedMediaType.isDiffBackwardCompatible(isRequest) ? - "Backward compatible" : "Broken compatibility") + .append(changedMediaType.isCompatible() ? "Backward compatible" : "Broken compatibility") .append(System.lineSeparator()); return sb.toString(); } diff --git a/src/main/java/com/qdesrame/openapi/diff/output/HtmlRender.java b/src/main/java/com/qdesrame/openapi/diff/output/HtmlRender.java index c6c30c49a..007033df9 100644 --- a/src/main/java/com/qdesrame/openapi/diff/output/HtmlRender.java +++ b/src/main/java/com/qdesrame/openapi/diff/output/HtmlRender.java @@ -121,14 +121,14 @@ private ContainerTag ol_changed(List changedOperations) { String desc = changedOperation.getSummary(); ContainerTag ul_detail = ul().withClass("detail"); - if (changedOperation.isDiffParam()) { + if (changedOperation.isChangedParam().isDifferent()) { ul_detail.with(li().with(h3("Parameters")).with(ul_param(changedOperation.getChangedParameters()))); } - if (changedOperation.isDiffRequest()) { + if (changedOperation.isChangedRequest().isDifferent()) { ul_detail.with(li().with(h3("Request")).with(ul_request(changedOperation.getChangedRequestBody().getChangedContent()))); } else { } - if (changedOperation.isDiffResponse()) { + if (changedOperation.isChangedResponse().isDifferent()) { ul_detail.with(li().with(h3("Response")).with(ul_response(changedOperation.getChangedApiResponse()))); } ol.with(li().with(span(method).withClass(method)).withText(pathUrl + " ").with(span(desc)) diff --git a/src/main/java/com/qdesrame/openapi/diff/output/MarkdownRender.java b/src/main/java/com/qdesrame/openapi/diff/output/MarkdownRender.java index ac805e232..92ea09d2c 100644 --- a/src/main/java/com/qdesrame/openapi/diff/output/MarkdownRender.java +++ b/src/main/java/com/qdesrame/openapi/diff/output/MarkdownRender.java @@ -81,13 +81,13 @@ private String listEndpoints(List changedOperations) { changedOperations.stream().map(operation -> { StringBuilder details = new StringBuilder() .append(itemEndpoint(operation.getHttpMethod().toString(), operation.getPathUrl(), operation.getSummary())); - if (operation.isDiffParam()) { + if (operation.isChangedParam().isDifferent()) { details.append(titleH5("Parameters:")).append(parameters(operation.getChangedParameters())); } - if (operation.isDiffRequest()) { + if (operation.isChangedRequest().isDifferent()) { details.append(titleH5("Request:")).append(bodyContent(operation.getChangedRequestBody().getChangedContent())); } - if (operation.isDiffResponse()) { + if (operation.isChangedResponse().isDifferent()) { details.append(titleH5("Return Type:")).append(responses(operation.getChangedApiResponse())); } return details.toString(); diff --git a/src/main/java/com/qdesrame/openapi/diff/utils/ChangedUtils.java b/src/main/java/com/qdesrame/openapi/diff/utils/ChangedUtils.java new file mode 100644 index 000000000..36e8c0c9e --- /dev/null +++ b/src/main/java/com/qdesrame/openapi/diff/utils/ChangedUtils.java @@ -0,0 +1,23 @@ +package com.qdesrame.openapi.diff.utils; + +import com.qdesrame.openapi.diff.model.Changed; + +import java.util.Optional; + +public class ChangedUtils { + + public static boolean isUnchanged(Changed changed) { + return changed == null || changed.isUnchanged(); + } + + public static boolean isCompatible(Changed changed) { + return changed == null || changed.isCompatible(); + } + + public static Optional isChanged(T changed) { + if (isUnchanged(changed)) { + return Optional.empty(); + } + return Optional.of(changed); + } +} diff --git a/src/test/java/com/qdesrame/openapi/test/BackwardCompatibilityTest.java b/src/test/java/com/qdesrame/openapi/test/BackwardCompatibilityTest.java index 7a40eefc7..b0dca5573 100644 --- a/src/test/java/com/qdesrame/openapi/test/BackwardCompatibilityTest.java +++ b/src/test/java/com/qdesrame/openapi/test/BackwardCompatibilityTest.java @@ -13,6 +13,7 @@ public class BackwardCompatibilityTest { private final String OPENAPI_DOC2 = "backwardCompatibility/bc_2.yaml"; private final String OPENAPI_DOC3 = "backwardCompatibility/bc_3.yaml"; private final String OPENAPI_DOC4 = "backwardCompatibility/bc_4.yaml"; + private final String OPENAPI_DOC5 = "backwardCompatibility/bc_5.yaml"; @Test public void testNoChange() { @@ -43,4 +44,9 @@ public void testApiChangedOperationMissing() { public void testApiOperationChanged() { assertOpenApiBackwardCompatible(OPENAPI_DOC2, OPENAPI_DOC4, true); } + + @Test + public void testApiReadWriteOnlyPropertiesChanged() { + assertOpenApiBackwardCompatible(OPENAPI_DOC1, OPENAPI_DOC5, true); + } } diff --git a/src/test/java/com/qdesrame/openapi/test/ResponseHeaderDiffTest.java b/src/test/java/com/qdesrame/openapi/test/ResponseHeaderDiffTest.java index dd0c66d65..3d172ec63 100644 --- a/src/test/java/com/qdesrame/openapi/test/ResponseHeaderDiffTest.java +++ b/src/test/java/com/qdesrame/openapi/test/ResponseHeaderDiffTest.java @@ -29,7 +29,7 @@ public void testDiffDifferent() { Assert.assertTrue(changedResponses.size() > 0); Assert.assertTrue(changedResponses.containsKey("200")); ChangedHeaders changedHeaders = changedResponses.get("200").getChangedHeaders(); - Assert.assertTrue(changedHeaders.isDiff()); + Assert.assertTrue(changedHeaders.isDifferent()); Assert.assertTrue(changedHeaders.getChanged().size() == 1); Assert.assertTrue(changedHeaders.getIncreased().size() == 1); Assert.assertTrue(changedHeaders.getMissing().size() == 1); diff --git a/src/test/java/com/qdesrame/openapi/test/SecurityDiffTest.java b/src/test/java/com/qdesrame/openapi/test/SecurityDiffTest.java index ae348999b..4c97b087d 100644 --- a/src/test/java/com/qdesrame/openapi/test/SecurityDiffTest.java +++ b/src/test/java/com/qdesrame/openapi/test/SecurityDiffTest.java @@ -24,10 +24,10 @@ public void testDiffDifferent() { ChangedOperation changedOperation1 = changedOpenApi.getChangedOperations().stream().filter(x -> x.getPathUrl().equals("/pet/{petId}")).findFirst().get(); assertNotNull(changedOperation1); - assertFalse(changedOperation1.isDiffBackwardCompatible()); + assertFalse(changedOperation1.isCompatible()); ChangedSecurityRequirements changedSecurityRequirements1 = changedOperation1.getChangedSecurityRequirements(); assertNotNull(changedSecurityRequirements1); - assertFalse(changedSecurityRequirements1.isDiffBackwardCompatible()); + assertFalse(changedSecurityRequirements1.isCompatible()); assertTrue(changedSecurityRequirements1.getIncreased().size() == 1); assertTrue(changedSecurityRequirements1.getChanged().size() == 1); ChangedSecurityRequirement changedSecurityRequirement1 = changedSecurityRequirements1.getChanged().get(0); @@ -39,10 +39,10 @@ public void testDiffDifferent() { ChangedOperation changedOperation2 = changedOpenApi.getChangedOperations().stream().filter(x -> x.getPathUrl().equals("/pet3")).findFirst().get(); assertNotNull(changedOperation2); - assertFalse(changedOperation2.isDiffBackwardCompatible()); + assertFalse(changedOperation2.isCompatible()); ChangedSecurityRequirements changedSecurityRequirements2 = changedOperation2.getChangedSecurityRequirements(); assertNotNull(changedSecurityRequirements2); - assertFalse(changedSecurityRequirements2.isDiffBackwardCompatible()); + assertFalse(changedSecurityRequirements2.isCompatible()); assertTrue(changedSecurityRequirements2.getChanged().size() == 1); ChangedSecurityRequirement changedSecurityRequirement2 = changedSecurityRequirements2.getChanged().get(0); assertTrue(changedSecurityRequirement2.getChanged().size() == 1); @@ -52,7 +52,7 @@ public void testDiffDifferent() { ChangedOperation changedOperation3 = changedOpenApi.getChangedOperations().stream().filter(x -> x.getPathUrl().equals("/pet/findByStatus2")).findFirst().get(); assertNotNull(changedOperation3); - assertTrue(changedOperation3.isDiffBackwardCompatible()); + assertTrue(changedOperation3.isCompatible()); ChangedSecurityRequirements changedSecurityRequirements3 = changedOperation3.getChangedSecurityRequirements(); assertNotNull(changedSecurityRequirements3); assertTrue(changedSecurityRequirements3.getIncreased().size() == 1); diff --git a/src/test/java/com/qdesrame/openapi/test/TestUtils.java b/src/test/java/com/qdesrame/openapi/test/TestUtils.java index 7286b7421..f6b4bcfcc 100644 --- a/src/test/java/com/qdesrame/openapi/test/TestUtils.java +++ b/src/test/java/com/qdesrame/openapi/test/TestUtils.java @@ -3,12 +3,16 @@ import com.qdesrame.openapi.diff.OpenApiCompare; import com.qdesrame.openapi.diff.model.ChangedOpenApi; import org.junit.Assert; +import org.slf4j.Logger; + +import static org.slf4j.LoggerFactory.getLogger; public class TestUtils { + public static final Logger LOG = getLogger(TestUtils.class); public static void assertOpenApiAreEquals(String oldSpec, String newSpec) { ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec); - + LOG.info("Result: {}", changedOpenApi.isChanged().getValue()); Assert.assertTrue(changedOpenApi.getNewEndpoints().isEmpty()); Assert.assertTrue(changedOpenApi.getMissingEndpoints().isEmpty()); Assert.assertTrue(changedOpenApi.getChangedOperations().isEmpty()); @@ -16,7 +20,7 @@ public static void assertOpenApiAreEquals(String oldSpec, String newSpec) { public static void assertOpenApiChangedEndpoints(String oldSpec, String newSpec) { ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec); - + LOG.info("Result: {}", changedOpenApi.isChanged().getValue()); Assert.assertTrue(changedOpenApi.getNewEndpoints().isEmpty()); Assert.assertTrue(changedOpenApi.getMissingEndpoints().isEmpty()); Assert.assertTrue(changedOpenApi.getChangedOperations().size() > 0); @@ -24,13 +28,13 @@ public static void assertOpenApiChangedEndpoints(String oldSpec, String newSpec) public static void assertOpenApiBackwardCompatible(String oldSpec, String newSpec, boolean isDiff) { ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec); - Assert.assertTrue(changedOpenApi.isDiff() == isDiff); - Assert.assertTrue(changedOpenApi.isDiffBackwardCompatible()); + LOG.info("Result: {}", changedOpenApi.isChanged().getValue()); + Assert.assertTrue(changedOpenApi.isCompatible()); } public static void assertOpenApiBackwardIncompatible(String oldSpec, String newSpec) { ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec); - Assert.assertTrue(changedOpenApi.isDiff()); - Assert.assertTrue(!changedOpenApi.isDiffBackwardCompatible()); + LOG.info("Result: {}", changedOpenApi.isChanged().getValue()); + Assert.assertTrue(changedOpenApi.isIncompatible()); } } diff --git a/src/test/resources/backwardCompatibility/bc_1.yaml b/src/test/resources/backwardCompatibility/bc_1.yaml index 32a970a3a..8247d2fcb 100644 --- a/src/test/resources/backwardCompatibility/bc_1.yaml +++ b/src/test/resources/backwardCompatibility/bc_1.yaml @@ -112,6 +112,9 @@ components: properties: bark: type: string + test: + writeOnly: true + type: string Lizard: type: object properties: diff --git a/src/test/resources/backwardCompatibility/bc_5.yaml b/src/test/resources/backwardCompatibility/bc_5.yaml new file mode 100644 index 000000000..6b282ba48 --- /dev/null +++ b/src/test/resources/backwardCompatibility/bc_5.yaml @@ -0,0 +1,131 @@ +openapi: 3.0.0 +servers: + - url: 'http://petstore.swagger.io/v2' +info: + description: >- + This is a sample server Petstore server. You can find out more about + Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, + #swagger](http://swagger.io/irc/). For this sample, you can use the api key + `special-key` to test the authorization filters. + version: 1.0.0 + title: Swagger Petstore + termsOfService: 'http://swagger.io/terms/' + contact: + email: apiteam@swagger.io + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +tags: + - name: pet + description: Everything about your Pets + externalDocs: + description: Find out more + url: 'http://swagger.io' + - name: store + description: Access to Petstore orders + - name: user + description: Operations about user + externalDocs: + description: Find out more about our store + url: 'http://swagger.io' +paths: + /pet/findByStatus: + get: + tags: + - pet + summary: Finds Pets by status + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - name: status + in: query + description: Status values that need to be considered for filter + required: true + explode: true + schema: + type: array + items: + type: string + maxLength: 16 + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: object + properties: + pets: + type: array + items: + $ref: '#/components/schemas/Dog' + '400': + description: Invalid status value + security: + - petstore_auth: + - 'write:pets' + - 'read:pets' +externalDocs: + description: Find out more about Swagger + url: 'http://swagger.io' +components: + requestBodies: + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + securitySchemes: + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: 'http://petstore.swagger.io/oauth/dialog' + scopes: + 'write:pets': modify pets in your account + 'read:pets': read your pets + api_key: + type: apiKey + name: api_key + in: header + schemas: + Pet: + type: object + required: + - pet_type + properties: + pet_type: + type: string + discriminator: + propertyName: pet_type + mapping: + cachorro: Dog + Cat: + type: object + properties: + name: + type: string + Dog: + type: object + properties: + bark: + type: string + test: + type: string + Lizard: + type: object + properties: + lovesRocks: + type: boolean + + MyResponseType: + oneOf: + - $ref: '#/components/schemas/Cat' + - $ref: '#/components/schemas/Dog' + - $ref: '#/components/schemas/Lizard' + discriminator: + propertyName: pet_type + mapping: + dog: '#/components/schemas/Dog' \ No newline at end of file From bc449642b5d322160dce738e664cdcaf58f0fb68 Mon Sep 17 00:00:00 2001 From: Quentin Desrame Date: Thu, 19 Apr 2018 10:15:09 +0200 Subject: [PATCH 2/4] Update version to 2.0.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a71007824..ef131c531 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.qdesrame openapi-diff - 1.2.1-SNAPSHOT + 2.0.0-SNAPSHOT jar openapi-diff From 9773e1ac696200ce8223206f688e8401b77f54eb Mon Sep 17 00:00:00 2001 From: Quentin Desrame Date: Thu, 19 Apr 2018 11:20:17 +0200 Subject: [PATCH 3/4] Fix DiffContext bug --- .../openapi/diff/compare/ApiResponseDiff.java | 2 - .../openapi/diff/compare/OperationDiff.java | 4 +- .../openapi/diff/compare/PathDiff.java | 3 +- .../openapi/diff/compare/RequestBodyDiff.java | 3 - .../openapi/diff/model/DiffContext.java | 80 ++++++++++++++++++- .../resources/backwardCompatibility/bc_2.yaml | 3 + .../resources/backwardCompatibility/bc_3.yaml | 3 + .../resources/backwardCompatibility/bc_4.yaml | 3 + 8 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java index 7cdf5b974..faf5867ca 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ApiResponseDiff.java @@ -29,8 +29,6 @@ public Optional diff(ApiResponses left, ApiResponses right, changedApiResponse.setAddResponses(responseMapKeyDiff.getIncreased()); changedApiResponse.setMissingResponses(responseMapKeyDiff.getMissing()); List sharedResponseCodes = responseMapKeyDiff.getSharedKey(); - context.setRequest(false); - context.setResponse(true); Map resps = new HashMap<>(); for (String responseCode : sharedResponseCodes) { openApiDiff.getResponseDiff().diff(left.get(responseCode), right.get(responseCode), context) diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java index cc50534ee..5e17ecc05 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/OperationDiff.java @@ -29,7 +29,7 @@ public Optional diff(Operation oldOperation, Operation newOper changedOperation.setDeprecated(!Boolean.TRUE.equals(oldOperation.getDeprecated()) && Boolean.TRUE.equals(newOperation.getDeprecated())); if (oldOperation.getRequestBody() != null || newOperation.getRequestBody() != null) { - openApiDiff.getRequestBodyDiff().diff(oldOperation.getRequestBody(), newOperation.getRequestBody(), context) + openApiDiff.getRequestBodyDiff().diff(oldOperation.getRequestBody(), newOperation.getRequestBody(), context.copyAsRequest()) .ifPresent(changedOperation::setChangedRequestBody); } @@ -40,7 +40,7 @@ public Optional diff(Operation oldOperation, Operation newOper }); if (oldOperation.getResponses() != null || newOperation.getResponses() != null) { - openApiDiff.getApiResponseDiff().diff(oldOperation.getResponses(), newOperation.getResponses(), context) + openApiDiff.getApiResponseDiff().diff(oldOperation.getResponses(), newOperation.getResponses(), context.copyAsResponse()) .ifPresent(changedOperation::setChangedApiResponse); } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java index ea87f7cce..883a43611 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java @@ -31,8 +31,7 @@ public Optional diff(PathItem left, PathItem right, DiffContext con for (PathItem.HttpMethod method : sharedMethods) { Operation oldOperation = oldOperationMap.get(method); Operation newOperation = newOperationMap.get(method); - context.setMethod(method); - openApiDiff.getOperationDiff().diff(oldOperation, newOperation, context).ifPresent(changedPath.getChanged()::add); + openApiDiff.getOperationDiff().diff(oldOperation, newOperation, context.copyWithMethod(method)).ifPresent(changedPath.getChanged()::add); } return isChanged(changedPath); } diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java b/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java index 1ce7df07b..adadc4b69 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/RequestBodyDiff.java @@ -46,9 +46,6 @@ protected Optional computeDiff(HashSet refSet, Reque newRequestContent = newRequestBody.getContent(); } } - context.setRequest(true); - context.setResponse(false); - ChangedRequestBody changedRequestBody = new ChangedRequestBody(oldRequestBody, newRequestBody, context); boolean leftRequired = oldRequestBody != null && Boolean.TRUE.equals(oldRequestBody.getRequired()); diff --git a/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java index 4e0ede11b..c686ed1e1 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java @@ -1,16 +1,13 @@ package com.qdesrame.openapi.diff.model; import io.swagger.v3.oas.models.PathItem; -import lombok.Getter; -import lombok.Setter; +import java.util.HashMap; import java.util.Map; /** * Created by Quentin Desramé on 04/04/17. */ -@Getter -@Setter public class DiffContext { private String url; @@ -18,4 +15,79 @@ public class DiffContext { private PathItem.HttpMethod method; private boolean response; private boolean request; + + public DiffContext() { + parameters = new HashMap<>(); + response = false; + request = true; + } + + public DiffContext copyWithMethod(PathItem.HttpMethod method) { + return copy().setMethod(method); + } + + public DiffContext copyAsRequest() { + return copy().setRequest(); + } + + public DiffContext copyAsResponse() { + return copy().setResponse(); + } + + private DiffContext setRequest() { + this.request = true; + this.response = false; + return this; + } + + private DiffContext setResponse() { + this.response = true; + this.request = false; + return this; + } + + public boolean isResponse() { + return this.response; + } + + public boolean isRequest() { + return this.request; + } + + public String getUrl() { + return url; + } + + public DiffContext setUrl(String url) { + this.url = url; + return this; + } + + public PathItem.HttpMethod getMethod() { + return method; + } + + private DiffContext setMethod(PathItem.HttpMethod method) { + this.method = method; + return this; + } + + private DiffContext copy() { + DiffContext context = new DiffContext(); + context.url = this.url; + context.parameters = this.parameters; + context.method = this.method; + context.response = this.response; + context.request = this.request; + return context; + } + + public Map getParameters() { + return parameters; + } + + public DiffContext setParameters(Map parameters) { + this.parameters = parameters; + return this; + } } diff --git a/src/test/resources/backwardCompatibility/bc_2.yaml b/src/test/resources/backwardCompatibility/bc_2.yaml index 86c978162..f8c6d7dc0 100644 --- a/src/test/resources/backwardCompatibility/bc_2.yaml +++ b/src/test/resources/backwardCompatibility/bc_2.yaml @@ -131,6 +131,9 @@ components: properties: bark: type: string + test: + writeOnly: true + type: string Lizard: type: object properties: diff --git a/src/test/resources/backwardCompatibility/bc_3.yaml b/src/test/resources/backwardCompatibility/bc_3.yaml index 45fa7ce59..456fc0553 100644 --- a/src/test/resources/backwardCompatibility/bc_3.yaml +++ b/src/test/resources/backwardCompatibility/bc_3.yaml @@ -144,6 +144,9 @@ components: properties: bark: type: string + test: + writeOnly: true + type: string Lizard: type: object properties: diff --git a/src/test/resources/backwardCompatibility/bc_4.yaml b/src/test/resources/backwardCompatibility/bc_4.yaml index 27100d04d..5de739f84 100644 --- a/src/test/resources/backwardCompatibility/bc_4.yaml +++ b/src/test/resources/backwardCompatibility/bc_4.yaml @@ -136,6 +136,9 @@ components: properties: bark: type: string + test: + writeOnly: true + type: string Lizard: type: object properties: From cea2a24ffcc2f03227a3ef5e4e86bc863b8e6ac6 Mon Sep 17 00:00:00 2001 From: Quentin Desrame Date: Thu, 19 Apr 2018 15:21:39 +0200 Subject: [PATCH 4/4] Update cache to handle DiffContext --- .../openapi/diff/compare/CacheKey.java | 43 +++++++++++++++++++ .../diff/compare/ReferenceDiffCache.java | 25 ++++------- .../openapi/diff/model/DiffContext.java | 30 +++++++++++++ 3 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/qdesrame/openapi/diff/compare/CacheKey.java diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/CacheKey.java b/src/main/java/com/qdesrame/openapi/diff/compare/CacheKey.java new file mode 100644 index 000000000..209a1113f --- /dev/null +++ b/src/main/java/com/qdesrame/openapi/diff/compare/CacheKey.java @@ -0,0 +1,43 @@ +package com.qdesrame.openapi.diff.compare; + +import com.qdesrame.openapi.diff.model.DiffContext; +import lombok.Getter; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +@Getter +public final class CacheKey { + private final String left; + private final String right; + private final DiffContext context; + + public CacheKey(final String left, final String right, final DiffContext context) { + this.left = left; + this.right = right; + this.context = context; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + CacheKey cacheKey = (CacheKey) o; + + return new EqualsBuilder() + .append(left, cacheKey.left) + .append(right, cacheKey.right) + .append(context, cacheKey.context) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(left) + .append(right) + .append(context) + .toHashCode(); + } +} diff --git a/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java b/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java index 69fbc7a01..7458e93ff 100644 --- a/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java +++ b/src/main/java/com/qdesrame/openapi/diff/compare/ReferenceDiffCache.java @@ -11,33 +11,25 @@ * Created by adarsh.sharma on 07/01/18. */ public abstract class ReferenceDiffCache { - private Map> refDiffMap; + private Map refDiffMap; public ReferenceDiffCache() { this.refDiffMap = new HashMap<>(); } - private Optional getFromCache(String leftRef, String rightRef) { - Optional> changedSchemaMap = Optional.ofNullable(refDiffMap.get(leftRef)); - if (changedSchemaMap.isPresent()) { - return Optional.ofNullable(changedSchemaMap.get().get(rightRef)); - } - return Optional.empty(); + private Optional getFromCache(CacheKey cacheKey) { + return Optional.ofNullable(refDiffMap.get(cacheKey)); } - private void addToCache(String leftRef, String rightRef, D changed) { - Map changedSchemaMap = refDiffMap.computeIfAbsent(leftRef, k -> new HashMap<>()); - changedSchemaMap.put(rightRef, changed); + private void addToCache(CacheKey cacheKey, D changed) { + refDiffMap.put(cacheKey, changed); } - // public Optional cachedDiff(HashSet refSet, C left, C right, String leftRef, String rightRef) { -// return cachedDiff(refSet, left, right, leftRef, rightRef, null); -// } -// public Optional cachedDiff(HashSet refSet, C left, C right, String leftRef, String rightRef, DiffContext context) { boolean areBothRefParameters = leftRef != null && rightRef != null; if (areBothRefParameters) { - Optional changedFromRef = getFromCache(leftRef, rightRef); + CacheKey key = new CacheKey(leftRef, rightRef, context); + Optional changedFromRef = getFromCache(key); if (changedFromRef.isPresent()) { return changedFromRef; } else { @@ -47,9 +39,8 @@ public Optional cachedDiff(HashSet refSet, C left, C right, String le } else { refSet.add(refKey); Optional changed = computeDiff(refSet, left, right, context); - addToCache(leftRef, rightRef, changed.orElse(null)); + addToCache(key, changed.orElse(null)); refSet.remove(refKey); - return changed; } } diff --git a/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java index c686ed1e1..12392a6e5 100644 --- a/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java +++ b/src/main/java/com/qdesrame/openapi/diff/model/DiffContext.java @@ -1,6 +1,8 @@ package com.qdesrame.openapi.diff.model; import io.swagger.v3.oas.models.PathItem; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; import java.util.HashMap; import java.util.Map; @@ -90,4 +92,32 @@ public DiffContext setParameters(Map parameters) { this.parameters = parameters; return this; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + DiffContext that = (DiffContext) o; + + return new EqualsBuilder() + .append(response, that.response) + .append(request, that.request) + .append(url, that.url) + .append(parameters, that.parameters) + .append(method, that.method) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(url) + .append(parameters) + .append(method) + .append(response) + .append(request) + .toHashCode(); + } }