Skip to content

Commit

Permalink
merge swagger methods of mutually exclusive media types; fixes #1128
Browse files Browse the repository at this point in the history
  • Loading branch information
stoicflame committed Mar 14, 2023
1 parent 3f2a290 commit b22310e
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* © 2023 by Intellectual Reserve, Inc. All rights reserved.
*/
package com.webcohesion.enunciate.modules.swagger;

import com.webcohesion.enunciate.api.resources.Entity;
import com.webcohesion.enunciate.api.resources.MediaTypeDescriptor;
import com.webcohesion.enunciate.javac.javadoc.JavaDoc;

import javax.lang.model.element.AnnotationMirror;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Function;

public class SwaggerEntity implements Entity {

private final List<Entity> delegates;

public SwaggerEntity(List<Entity> delegates) {
this.delegates = delegates;
}

private <R> R doDelegation(Function<Entity, R> accessor) {
return this.delegates.stream().map(accessor)
.filter(Objects::nonNull)
.findFirst().orElse(null);
}

@Override
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
return doDelegation(delegate -> delegate.getAnnotation(annotationType));
}

@Override
public Map<String, AnnotationMirror> getAnnotations() {
LinkedHashMap<String, AnnotationMirror> annotations = new LinkedHashMap<>();
this.delegates.forEach(delegate -> annotations.putAll(delegate.getAnnotations()));
return annotations;
}

@Override
public String getDescription() {
return doDelegation(Entity::getDescription);
}

@Override
public List<? extends MediaTypeDescriptor> getMediaTypes() {
ArrayList<MediaTypeDescriptor> mediaTypes = new ArrayList<>();
this.delegates.forEach(delegate -> mediaTypes.addAll(delegate.getMediaTypes()));
return mediaTypes;
}

@Override
public JavaDoc getJavaDoc() {
return doDelegation(Entity::getJavaDoc);
}

@Override
public boolean isRequired() {
return this.delegates.stream().anyMatch(Entity::isRequired);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*
* © 2023 by Intellectual Reserve, Inc. All rights reserved.
*/
package com.webcohesion.enunciate.modules.swagger;

import com.webcohesion.enunciate.api.resources.*;
import com.webcohesion.enunciate.facets.Facet;
import com.webcohesion.enunciate.javac.javadoc.JavaDoc;
import org.apache.commons.lang3.StringUtils;

import javax.lang.model.element.AnnotationMirror;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class SwaggerMethod implements Method {

private final String httpMethod;
private final List<Method> delegates = new ArrayList<>();

public SwaggerMethod(Method delegate) {
this.delegates.add(delegate);
this.httpMethod = delegate.getHttpMethod();
}

public void merge(Method delegate) {
if (!StringUtils.equals(delegate.getHttpMethod(), httpMethod)) {
throw new IllegalArgumentException();
}
this.delegates.add(delegate);
}

private <R> R doDelegation(Function<Method, R> accessor) {
return this.delegates.stream().map(accessor)
.filter(Objects::nonNull)
.findFirst().orElse(null);
}

@Override
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
return doDelegation(delegate -> delegate.getAnnotation(annotationType));
}

@Override
public Map<String, AnnotationMirror> getAnnotations() {
LinkedHashMap<String, AnnotationMirror> annotations = new LinkedHashMap<>();
this.delegates.forEach(delegate -> annotations.putAll(delegate.getAnnotations()));
return annotations;
}

@Override
public Set<String> getStyles() {
TreeSet<String> styles = new TreeSet<>();
this.delegates.forEach(delegate -> styles.addAll(delegate.getStyles()));
return styles;
}

@Override
public Resource getResource() {
return doDelegation(Method::getResource);
}

@Override
public String getLabel() {
return doDelegation(Method::getLabel);
}

@Override
public String getDeveloperLabel() {
return doDelegation(Method::getDeveloperLabel);
}

@Override
public String getHttpMethod() {
return this.httpMethod;
}

@Override
public String getSlug() {
return doDelegation(Method::getSlug);
}

@Override
public String getSummary() {
return doDelegation(Method::getSummary);
}

@Override
public String getDescription() {
return doDelegation(Method::getDescription);
}

@Override
public String getDeprecated() {
return doDelegation(Method::getDeprecated);
}

@Override
public String getSince() {
return doDelegation(Method::getSince);
}

@Override
public List<String> getSeeAlso() {
ArrayList<String> seeAlsos = new ArrayList<>();
this.delegates.forEach(delegate -> seeAlsos.addAll(delegate.getSeeAlso()));
return seeAlsos;
}

@Override
public String getVersion() {
return doDelegation(Method::getVersion);
}

@Override
public boolean isIncludeDefaultParameterValues() {
return this.delegates.stream().anyMatch(Method::isIncludeDefaultParameterValues);
}

@Override
public List<? extends Parameter> getParameters() {
Set<Parameter> alreadyDeclaredParams = new TreeSet<>(Comparator.comparing(Parameter::getName));
List<Parameter> parameters = new ArrayList<>();
this.delegates.stream().flatMap(delegate -> delegate.getParameters().stream()).filter(alreadyDeclaredParams::add).forEach(parameters::add);
return parameters;
}

@Override
public boolean isHasParameterConstraints() {
return this.delegates.stream().anyMatch(Method::isHasParameterConstraints);
}

@Override
public boolean isHasParameterMultiplicity() {
return this.delegates.stream().anyMatch(Method::isHasParameterMultiplicity);
}

@Override
public Entity getRequestEntity() {
List<Entity> requestEntities = this.delegates.stream().map(Method::getRequestEntity).filter(Objects::nonNull).collect(Collectors.toList());
return requestEntities.isEmpty() ? null : new SwaggerEntity(requestEntities);
}

@Override
public List<? extends StatusCode> getResponseCodes() {
ArrayList<StatusCode> statusCodes = new ArrayList<>();
this.delegates.forEach(delegate -> statusCodes.addAll(delegate.getResponseCodes()));
return statusCodes;
}

@Override
public Entity getResponseEntity() {
List<Entity> responseEntities = this.delegates.stream().map(Method::getResponseEntity).filter(Objects::nonNull).collect(Collectors.toList());
return responseEntities.isEmpty() ? null : new SwaggerEntity(responseEntities);
}

@Override
public List<? extends StatusCode> getWarnings() {
ArrayList<StatusCode> statusCodes = new ArrayList<>();
this.delegates.forEach(delegate -> statusCodes.addAll(delegate.getWarnings()));
return statusCodes;
}

@Override
public List<? extends Parameter> getResponseHeaders() {
Set<Parameter> alreadyDeclared = new TreeSet<>(Comparator.comparing(Parameter::getName));
List<Parameter> parameters = new ArrayList<>();
this.delegates.stream().flatMap(delegate -> delegate.getResponseHeaders().stream()).filter(alreadyDeclared::add).forEach(parameters::add);
return parameters;
}

@Override
public Set<String> getSecurityRoles() {
TreeSet<String> securityRoles = new TreeSet<>();
this.delegates.forEach(delegate -> securityRoles.addAll(delegate.getSecurityRoles()));
return securityRoles;
}

@Override
public JavaDoc getJavaDoc() {
return doDelegation(Method::getJavaDoc);
}

@Override
public Example getExample() {
return doDelegation(Method::getExample);
}

@Override
public Set<Facet> getFacets() {
TreeSet<Facet> facets = new TreeSet<>();
this.delegates.forEach(delegate -> facets.addAll(delegate.getFacets()));
return facets;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void writeTo(File srcDir) throws IOException {
resourcePath = "/" + resourceGroup.getRelativeContextPath() + resourcePath;
}
if (path.equals(resourcePath)) {
swaggerResource.getMethods().addAll(resource.getMethods());
resource.getMethods().forEach(swaggerResource::addMethod);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,34 @@

import com.webcohesion.enunciate.api.resources.Method;
import com.webcohesion.enunciate.api.resources.ResourceGroup;
import org.apache.commons.lang3.StringUtils;

import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;

public class SwaggerResource {

private final ResourceGroup resourceGroup;
private final Set<Method> methods;
private final Set<SwaggerMethod> methods = new TreeSet<>(Comparator.comparing(SwaggerMethod::getHttpMethod));

public SwaggerResource(ResourceGroup resourceGroup) {
this.resourceGroup = resourceGroup;
this.methods = new TreeSet<>(Comparator.comparing(Method::getHttpMethod));
}

public ResourceGroup getResourceGroup() {
return resourceGroup;
}

public Set<Method> getMethods() {
return methods;
return Collections.unmodifiableSet(methods);
}

public void addMethod(Method method) {
this.methods.stream().filter(sm -> StringUtils.equals(sm.getHttpMethod(), method.getHttpMethod())).findAny()
.ifPresentOrElse(existing -> existing.merge(method), () -> methods.add(new SwaggerMethod(method)));
}

public String getLabel() {
Expand Down

0 comments on commit b22310e

Please sign in to comment.