Skip to content

Commit

Permalink
Require a name match for annotations on a method (1.x)
Browse files Browse the repository at this point in the history
- Allow an omitted name to to match a specified name (supports case
where `@Parameter` has no `name` and equivalent JAX-RS annotation has a
name - see smallrye#285)
  • Loading branch information
MikeEdgar committed May 26, 2020
1 parent 43ee55c commit b96fa9e
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1398,15 +1398,17 @@ ParameterContext getParameterContext(ParameterContextKey key, AnnotationTarget t
}

boolean haveSameAnnotatedTarget(ParameterContext context, AnnotationTarget target, String name) {
boolean nameMatches = Objects.equals(context.name, name);
/*
* Consider names to match if one is unspecified or they are equal.
*/
boolean nameMatches = (context.name == null || name == null || Objects.equals(context.name, name));

if (target.equals(context.target)) {
/*
* This logic formerly also required that the parameter names matched
* (nameMatches == true) or that the kind of the target was not a
* method.
* The name must match for annotations on a method because it is
* ambiguous which parameters is being referenced.
*/
return true;
return nameMatches || target.kind() != Kind.METHOD;
}

if (nameMatches && target.kind() == Kind.METHOD && context.target.kind() == Kind.METHOD_PARAMETER) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.enterprise.context.RequestScoped;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
Expand All @@ -40,9 +44,13 @@
import javax.ws.rs.core.Response;

import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.headers.Header;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameters;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
Expand Down Expand Up @@ -492,4 +500,78 @@ public Response getWithBeanParams(@BeanParam BeanParamImpl params) {
return null;
}
}

/*************************************************************************/
/*
* Test case derived from original example in SmallRye OpenAPI issue #330.
*
* https://github.com/smallrye/smallrye-open-api/issues/330
*
*/

@Test
public void testMethodTargetParametersWithoutJAXRS() throws IOException, JSONException {
Index i = indexOf(MethodTargetParametersResource.class,
MethodTargetParametersResource.PagedResponse.class);
OpenApiAnnotationScanner scanner = new OpenApiAnnotationScanner(emptyConfig(), i);
OpenAPI result = scanner.scan();
printToConsole(result);
assertJsonEquals("params.method-target-nojaxrs.json", result);
}

@Path("/policies")
@Produces("application/json")
@Consumes("application/json")
@RequestScoped
static class MethodTargetParametersResource {
static class PagedResponse<T> {
public Map<String, Long> meta = new HashMap<>(1);
public Map<String, String> links = new HashMap<>(3);
public List<T> data = new ArrayList<>();
}

@Operation(summary = "Return all policies for a given account")
@GET
@Path("/")
@Parameters({
@Parameter(name = "offset", in = ParameterIn.QUERY, description = "Page number, starts 0, if not specified uses 0.", schema = @Schema(type = SchemaType.INTEGER)),
@Parameter(name = "limit", in = ParameterIn.QUERY, description = "Number of items per page, if not specified uses 10. "
+ "NO_LIMIT can be used to specify an unlimited page, when specified it ignores the offset", schema = @Schema(type = SchemaType.INTEGER)),
@Parameter(name = "sortColumn", in = ParameterIn.QUERY, description = "Column to sort the results by", schema = @Schema(type = SchemaType.STRING, enumeration = {
"name",
"description",
"is_enabled",
"mtime"
})),
@Parameter(name = "sortDirection", in = ParameterIn.QUERY, description = "Sort direction used", schema = @Schema(type = SchemaType.STRING, enumeration = {
"asc",
"desc"
})),
@Parameter(name = "filter[name]", in = ParameterIn.QUERY, description = "Filtering policies by the name depending on the Filter operator used.", schema = @Schema(type = SchemaType.STRING)),
@Parameter(name = "filter:op[name]", in = ParameterIn.QUERY, description = "Operations used with the filter", schema = @Schema(type = SchemaType.STRING, enumeration = {
"equal",
"like",
"ilike",
"not_equal"
}, defaultValue = "equal")),
@Parameter(name = "filter[description]", in = ParameterIn.QUERY, description = "Filtering policies by the description depending on the Filter operator used.", schema = @Schema(type = SchemaType.STRING)),
@Parameter(name = "filter:op[description]", in = ParameterIn.QUERY, description = "Operations used with the filter", schema = @Schema(type = SchemaType.STRING, enumeration = {
"equal",
"like",
"ilike",
"not_equal"
}, defaultValue = "equal")),
@Parameter(name = "filter[is_enabled]", in = ParameterIn.QUERY, description = "Filtering policies by the is_enabled field."
+
"Defaults to true if no operand is given.", schema = @Schema(type = SchemaType.STRING, defaultValue = "true", enumeration = {
"true", "false" })),
})
@APIResponse(responseCode = "400", description = "Bad parameter for sorting was passed")
@APIResponse(responseCode = "404", description = "No policies found for customer")
@APIResponse(responseCode = "403", description = "Individual permissions missing to complete action")
@APIResponse(responseCode = "200", description = "Policies found", content = @Content(schema = @Schema(implementation = PagedResponse.class)), headers = @Header(name = "TotalCount", description = "Total number of items found", schema = @Schema(type = SchemaType.INTEGER)))
public Response getPoliciesForCustomer() {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
{
"openapi": "3.0.1",
"paths": {
"/policies": {
"get": {
"summary": "Return all policies for a given account",
"parameters": [
{
"name": "filter:op[description]",
"in": "query",
"description": "Operations used with the filter",
"schema": {
"default": "equal",
"enum": [
"equal",
"like",
"ilike",
"not_equal"
],
"type": "string"
}
},
{
"name": "filter:op[name]",
"in": "query",
"description": "Operations used with the filter",
"schema": {
"default": "equal",
"enum": [
"equal",
"like",
"ilike",
"not_equal"
],
"type": "string"
}
},
{
"name": "filter[description]",
"in": "query",
"description": "Filtering policies by the description depending on the Filter operator used.",
"schema": {
"type": "string"
}
},
{
"name": "filter[is_enabled]",
"in": "query",
"description": "Filtering policies by the is_enabled field.Defaults to true if no operand is given.",
"schema": {
"default": "true",
"enum": [
"true",
"false"
],
"type": "string"
}
},
{
"name": "filter[name]",
"in": "query",
"description": "Filtering policies by the name depending on the Filter operator used.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"description": "Number of items per page, if not specified uses 10. NO_LIMIT can be used to specify an unlimited page, when specified it ignores the offset",
"schema": {
"type": "integer"
}
},
{
"name": "offset",
"in": "query",
"description": "Page number, starts 0, if not specified uses 0.",
"schema": {
"type": "integer"
}
},
{
"name": "sortColumn",
"in": "query",
"description": "Column to sort the results by",
"schema": {
"enum": [
"name",
"description",
"is_enabled",
"mtime"
],
"type": "string"
}
},
{
"name": "sortDirection",
"in": "query",
"description": "Sort direction used",
"schema": {
"enum": [
"asc",
"desc"
],
"type": "string"
}
}
],
"responses": {
"400": {
"description": "Bad parameter for sorting was passed"
},
"404": {
"description": "No policies found for customer"
},
"403": {
"description": "Individual permissions missing to complete action"
},
"200": {
"description": "Policies found",
"headers": {
"TotalCount": {
"description": "Total number of items found",
"style": "simple",
"schema": {
"type": "integer"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PagedResponse"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"PagedResponse": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object"
}
},
"links": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"meta": {
"type": "object",
"additionalProperties": {
"format": "int64",
"type": "integer"
}
}
}
}
}
}
}

0 comments on commit b96fa9e

Please sign in to comment.