Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve extension support #50

Merged
merged 3 commits into from
Jul 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public Optional<ChangedApiResponse> diff(ApiResponses left, ApiResponses right,
.ifPresent(changedResponse -> resps.put(responseCode, changedResponse));
}
changedApiResponse.setChangedResponses(resps);
openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context)
.ifPresent(changedApiResponse::setChangedExtensions);
return isChanged(changedApiResponse);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.qdesrame.openapi.diff.compare;

import com.qdesrame.openapi.diff.model.Change;
import com.qdesrame.openapi.diff.model.Changed;
import com.qdesrame.openapi.diff.model.DiffContext;

Expand All @@ -11,5 +12,10 @@ public interface ExtensionDiff {

String getName();

Optional<Changed> diff(Object left, Object right, DiffContext context);
Optional<Changed> diff(Change extension, DiffContext context);

default boolean isParentApplicable(Change.Type type, Object object, Object extension, DiffContext context) {
return true;
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.qdesrame.openapi.diff.compare;

import com.qdesrame.openapi.diff.model.Change;
import com.qdesrame.openapi.diff.model.Changed;
import com.qdesrame.openapi.diff.model.CompatibleChanged;
import com.qdesrame.openapi.diff.model.DiffContext;
import com.qdesrame.openapi.diff.model.schema.ChangedExtensions;

import java.util.*;
import java.util.function.Function;

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

Expand All @@ -21,23 +25,53 @@ public ExtensionsDiff(OpenApiDiff openApiDiff) {
}
}

public boolean isParentApplicable(Change.Type type, Object parent, Map<String, Object> extensions, DiffContext context) {
if (extensions.size() == 0) {
return true;
}
return extensions.entrySet().stream()
.map(entry -> executeExtension(entry.getKey(), extensionDiff -> extensionDiff.isParentApplicable(type, parent, entry.getValue(), context)))
.allMatch(aBoolean -> aBoolean.orElse(true));
}

public Optional<ExtensionDiff> getExtensionDiff(String name) {
return extensionsDiff.stream()
.filter(diff -> ("x-" + diff.getName()).equals(name))
.findFirst();
}

public <T> Optional<T> executeExtension(String name, Function<ExtensionDiff, T> predicate) {
return getExtensionDiff(name)
.map(extensionDiff -> extensionDiff.setOpenApiDiff(openApiDiff))
.map(predicate);
}

public Optional<ChangedExtensions> diff(Map<String, Object> left, Map<String, Object> right) {
return this.diff(left, right, null);
}

public Optional<ChangedExtensions> diff(Map<String, Object> left, Map<String, Object> right, DiffContext context) {
if (null == left) left = new LinkedHashMap<>();
if (null == right) right = new LinkedHashMap<>();
ChangedExtensions changedExtensions = new ChangedExtensions(left, new LinkedHashMap<>(right), context);
changedExtensions.getIncreased().putAll(right);
for (String key : left.keySet()) {
if (changedExtensions.getIncreased().containsKey(key)) {
Optional<ExtensionDiff> extensionDiff = extensionsDiff.stream()
.filter(diff -> ("x-" + diff.getName()).equals(key)).findFirst();
Object leftValue = left.get(key);
Object rightValue = changedExtensions.getIncreased().remove(key);
extensionDiff.ifPresent(diff -> diff.setOpenApiDiff(openApiDiff).diff(leftValue, rightValue, context)
.ifPresent(changed -> changedExtensions.getChanged().put(key, changed)));
Object leftValue = left.get(key);
if (right.containsKey(key)) {
Object rightValue = right.remove(key);
executeExtensionDiff(key, Change.changed(leftValue, rightValue), context)
.ifPresent(changed -> changedExtensions.getChanged().put(key, changed));
} else {
changedExtensions.getMissing().put(key, left.get(key));
executeExtensionDiff(key, Change.removed(leftValue), context)
.ifPresent(changed -> changedExtensions.getMissing().put(key, changed));
}
}
right.forEach((key, value) -> executeExtensionDiff(key, Change.added(value), context)
.ifPresent(changed -> changedExtensions.getIncreased().put(key, changed)));
return isChanged(changedExtensions);
}

private Optional<Changed> executeExtensionDiff(String name, Change change, DiffContext context) {
return executeExtension(name, diff -> diff.setOpenApiDiff(openApiDiff).diff(change, context))
.orElse(Optional.of(CompatibleChanged.compatible(change)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ protected Optional<ChangedHeader> computeDiff(HashSet<String> refSet, Header lef
changedHeader.setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
openApiDiff.getSchemaDiff().diff(new HashSet<>(), left.getSchema(), right.getSchema(), context.copyWithRequired(true)).ifPresent(changedHeader::setChangedSchema);
openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context).ifPresent(changedHeader::setChangedContent);

openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context)
.ifPresent(changedHeader::setChangedExtensions);
return isChanged(changedHeader);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import com.qdesrame.openapi.diff.model.ChangedOAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlow;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
import static java.util.Optional.ofNullable;

/**
* Created by adarsh.sharma on 12/01/18.
Expand All @@ -18,14 +20,20 @@ public OAuthFlowDiff(OpenApiDiff openApiDiff) {
this.openApiDiff = openApiDiff;
}

private static Map<String, Object> getExtensions(OAuthFlow oAuthFlow) {
return ofNullable(oAuthFlow).map(OAuthFlow::getExtensions).orElse(null);
}

public Optional<ChangedOAuthFlow> diff(OAuthFlow left, OAuthFlow right) {
ChangedOAuthFlow changedOAuthFlow = new ChangedOAuthFlow(left, right);
if (left != null && right != null) {
changedOAuthFlow.setChangedAuthorizationUrl(!Objects.equals(left.getAuthorizationUrl(), right.getAuthorizationUrl()));
changedOAuthFlow.setChangedTokenUrl(!Objects.equals(left.getTokenUrl(), right.getTokenUrl()));
changedOAuthFlow.setChangedRefreshUrl(!Objects.equals(left.getRefreshUrl(), right.getRefreshUrl()));
}

openApiDiff.getExtensionsDiff().diff(getExtensions(left), getExtensions(right))
.ifPresent(changedOAuthFlow::setChangedExtensions);
return isChanged(changedOAuthFlow);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.qdesrame.openapi.diff.model.ChangedOAuthFlows;
import io.swagger.v3.oas.models.security.OAuthFlows;

import java.util.Map;
import java.util.Optional;

import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
import static java.util.Optional.ofNullable;

/**
* Created by adarsh.sharma on 12/01/18.
Expand All @@ -17,6 +19,10 @@ public OAuthFlowsDiff(OpenApiDiff openApiDiff) {
this.openApiDiff = openApiDiff;
}

private static Map<String, Object> getExtensions(OAuthFlows oAuthFlow) {
return ofNullable(oAuthFlow).map(OAuthFlows::getExtensions).orElse(null);
}

public Optional<ChangedOAuthFlows> diff(OAuthFlows left, OAuthFlows right) {
ChangedOAuthFlows changedOAuthFlows = new ChangedOAuthFlows(left, right);
if (left != null && right != null) {
Expand All @@ -25,6 +31,9 @@ public Optional<ChangedOAuthFlows> 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);
}
openApiDiff.getExtensionsDiff().diff(getExtensions(left), getExtensions(right))
.ifPresent(changedOAuthFlows::setChangedExtensions);
return isChanged(changedOAuthFlows);
}

}
10 changes: 10 additions & 0 deletions src/main/java/com/qdesrame/openapi/diff/compare/OpenApiDiff.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.qdesrame.openapi.diff.compare;

import com.qdesrame.openapi.diff.model.*;
import com.qdesrame.openapi.diff.model.schema.ChangedExtensions;
import com.qdesrame.openapi.diff.utils.EndpointUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.PathItem;
Expand Down Expand Up @@ -47,6 +48,8 @@ public class OpenApiDiff {
private List<Endpoint> newEndpoints;
private List<Endpoint> missingEndpoints;
private List<ChangedOperation> changedOperations;
private ChangedExtensions changedExtensions;


/*
* @param oldSpecOpenApi
Expand Down Expand Up @@ -105,9 +108,15 @@ private ChangedOpenApi compare() {
changedOperations.addAll(changedPath.getChanged());
});
});
getExtensionsDiff().diff(oldSpecOpenApi.getExtensions(), newSpecOpenApi.getExtensions())
.ifPresent(this::setChangedExtension);
return getChangedOpenApi();
}

private void setChangedExtension(ChangedExtensions changedExtension) {
this.changedExtensions = changedExtension;
}

private void preProcess(OpenAPI openApi) {
List<SecurityRequirement> securityRequirements = openApi.getSecurity();

Expand All @@ -132,6 +141,7 @@ private ChangedOpenApi getChangedOpenApi() {
changedOpenApi.setNewSpecOpenApi(newSpecOpenApi);
changedOpenApi.setOldSpecOpenApi(oldSpecOpenApi);
changedOpenApi.setChangedOperations(changedOperations);
changedOpenApi.setChangedExtensions(changedExtensions);
return changedOpenApi;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public Optional<ChangedOperation> diff(Operation oldOperation, Operation newOper
.ifPresent(changedOperation::setChangedSecurityRequirements);
}

openApiDiff.getExtensionsDiff().diff(oldOperation.getExtensions(), newOperation.getExtensions(), context)
.ifPresent(changedOperation::setChangedExtensions);

return isChanged(changedOperation);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ protected Optional<ChangedParameter> computeDiff(HashSet<String> refSet, Paramet
}
openApiDiff.getContentDiff().diff(left.getContent(), right.getContent(), context)
.ifPresent(changedParameter::setChangedContent);

openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context)
.ifPresent(changedParameter::setChangedExtensions);
return isChanged(changedParameter);
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/qdesrame/openapi/diff/compare/PathDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public Optional<ChangedPath> diff(PathItem left, PathItem right, DiffContext con
Operation newOperation = newOperationMap.get(method);
openApiDiff.getOperationDiff().diff(oldOperation, newOperation, context.copyWithMethod(method)).ifPresent(changedPath.getChanged()::add);
}
openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context)
.ifPresent(changedPath::setChangedExtensions);
return isChanged(changedPath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
import io.swagger.v3.oas.models.parameters.RequestBody;

import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
import static java.util.Optional.ofNullable;

/**
* Created by adarsh.sharma on 28/12/17.
Expand All @@ -30,6 +32,10 @@ public Optional<ChangedRequestBody> diff(RequestBody left, RequestBody right, Di
return cachedDiff(new HashSet<>(), left, right, leftRef, rightRef, context);
}

private static Map<String, Object> getExtensions(RequestBody body) {
return ofNullable(body).map(RequestBody::getExtensions).orElse(null);
}

@Override
protected Optional<ChangedRequestBody> computeDiff(HashSet<String> refSet, RequestBody left, RequestBody right, DiffContext context) {
Content oldRequestContent = new Content();
Expand Down Expand Up @@ -59,6 +65,8 @@ protected Optional<ChangedRequestBody> computeDiff(HashSet<String> refSet, Reque
changedRequestBody.setChangeDescription(!Objects.equals(leftDescription, rightDescription));

openApiDiff.getContentDiff().diff(oldRequestContent, newRequestContent, context).ifPresent(changedRequestBody::setChangedContent);
openApiDiff.getExtensionsDiff().diff(getExtensions(left), getExtensions(right), context)
.ifPresent(changedRequestBody::setChangedExtensions);

return isChanged(changedRequestBody);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ protected Optional<ChangedResponse> computeDiff(HashSet<String> refSet, ApiRespo
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()));

openApiDiff.getExtensionsDiff().diff(left.getExtensions(), right.getExtensions(), context)
.ifPresent(changedResponse::setChangedExtensions);
return isChanged(changedResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ protected Optional<ChangedSecurityScheme> computeDiff(HashSet<String> refSet, Se
.getOpenIdConnectUrl()));
break;
}
openApiDiff.getExtensionsDiff().diff(leftSecurityScheme.getExtensions(), rightSecurityScheme.getExtensions(), context)
.ifPresent(changedSecurityScheme::setChangedExtensions);

return Optional.of(changedSecurityScheme);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.qdesrame.openapi.diff.compare.MapKeyDiff;
import com.qdesrame.openapi.diff.compare.OpenApiDiff;
import com.qdesrame.openapi.diff.model.Change;
import com.qdesrame.openapi.diff.model.ChangedSchema;
import com.qdesrame.openapi.diff.model.DiffContext;
import com.qdesrame.openapi.diff.model.ListDiff;
Expand All @@ -13,9 +14,9 @@
import lombok.Getter;

import java.util.*;
import java.util.stream.Collectors;

import static com.qdesrame.openapi.diff.utils.ChangedUtils.isChanged;
import static java.util.Optional.ofNullable;

@Getter
public class SchemaDiffResult {
Expand Down Expand Up @@ -60,8 +61,8 @@ public Optional<ChangedSchema> diff(HashSet<String> refSet, Components leftCompo

compareAdditionalProperties(refSet, left, right, context);

changedSchema.getIncreasedProperties().putAll(filterProperties(propertyDiff.getIncreased(), context));
changedSchema.getMissingProperties().putAll(filterProperties(propertyDiff.getMissing(), context));
changedSchema.getIncreasedProperties().putAll(filterProperties(Change.Type.ADDED, propertyDiff.getIncreased(), context));
changedSchema.getMissingProperties().putAll(filterProperties(Change.Type.REMOVED, propertyDiff.getMissing(), context));
return isApplicable(context);
}

Expand All @@ -73,10 +74,19 @@ protected Optional<ChangedSchema> isApplicable(DiffContext context) {
return isChanged(changedSchema);
}

private Map<String, Schema> filterProperties(Map<String, Schema> properties, DiffContext context) {
return properties.entrySet().stream()
.filter(entry -> isPropertyApplicable(entry.getValue(), context))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
private Map<String, Schema> filterProperties(Change.Type type, Map<String, Schema> properties, DiffContext context) {
Map<String, Schema> result = new LinkedHashMap<>();
for (Map.Entry<String, Schema> entry : properties.entrySet()) {
if (isPropertyApplicable(entry.getValue(), context)
&& openApiDiff.getExtensionsDiff()
.isParentApplicable(
type,
entry.getValue(),
ofNullable(entry.getValue().getExtensions()).orElse(new LinkedHashMap()), context)) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}

private boolean isPropertyApplicable(Schema schema, DiffContext context) {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/qdesrame/openapi/diff/model/Change.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.qdesrame.openapi.diff.model;

import lombok.Getter;

@Getter
public class Change<T> {
private final T oldValue;
private final T newValue;
private final Type type;

private Change(T oldValue, T newValue, Type type) {
this.oldValue = oldValue;
this.newValue = newValue;
this.type = type;
}

public static <T> Change<T> changed(T oldValue, T newValue) {
return new Change<>(oldValue, newValue, Type.CHANGED);
}

public static <T> Change<T> added(T newValue) {
return new Change<>(null, newValue, Type.ADDED);
}

public static <T> Change<T> removed(T oldValue) {
return new Change<>(oldValue, null, Type.REMOVED);
}

public enum Type {
ADDED,
CHANGED,
REMOVED
}
}
Loading