Skip to content

Commit

Permalink
Disabling Legacy Filter Dialect in Swagger Documentation (#1363)
Browse files Browse the repository at this point in the history
* Disabling Legacy Filter Dialect in Swagger Documentation

* Fixed test ordering issue

* Inspection rework

Co-authored-by: Aaron Klish <klish@verizonmedia.com>
  • Loading branch information
aklish and Aaron Klish committed Jun 3, 2020
1 parent aab3e45 commit bd51647
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 27 deletions.
Expand Up @@ -56,6 +56,8 @@ public class SwaggerBuilder {
protected Map<Integer, Response> globalResponses;
protected Set<Parameter> globalParams;
protected Set<Operator> filterOperators;
protected boolean supportLegacyDialect;
protected boolean supportRSQLDialect;

public static final Response UNAUTHORIZED_RESPONSE = new Response().description("Unauthorized");
public static final Response FORBIDDEN_RESPONSE = new Response().description("Forbidden");
Expand Down Expand Up @@ -495,33 +497,39 @@ private List<Parameter> getFilterParameters() {

List<Parameter> params = new ArrayList<>();

/* Add RSQL Disjoint Filter Query Param */
params.add(new QueryParameter()
.type("string")
.name("filter[" + typeName + "]")
.description("Filters the collection of " + typeName + " using a 'disjoint' RSQL expression"));

if (lineage.isEmpty()) {
/* Add RSQL Joined Filter Query Param */
if (supportRSQLDialect) {
/* Add RSQL Disjoint Filter Query Param */
params.add(new QueryParameter()
.type("string")
.name("filter")
.description("Filters the collection of " + typeName + " using a 'joined' RSQL expression"));
.name("filter[" + typeName + "]")
.description("Filters the collection of " + typeName
+ " using a 'disjoint' RSQL expression"));

if (lineage.isEmpty()) {
/* Add RSQL Joined Filter Query Param */
params.add(new QueryParameter()
.type("string")
.name("filter")
.description("Filters the collection of " + typeName
+ " using a 'joined' RSQL expression"));
}
}

for (Operator op : filterOperators) {
attributeNames.forEach((name) -> {
Class<?> attributeClass = dictionary.getType(type, name);

/* Only filter attributes that can be assigned to strings or primitives */
if (attributeClass.isPrimitive() || String.class.isAssignableFrom(attributeClass)) {
params.add(new QueryParameter()
.type("string")
.name("filter[" + typeName + "." + name + "][" + op.getNotation() + "]")
.description("Filters the collection of " + typeName + " by the attribute "
+ name + " " + "using the operator " + op.getNotation()));
}
});
if (supportLegacyDialect) {
for (Operator op : filterOperators) {
attributeNames.forEach((name) -> {
Class<?> attributeClass = dictionary.getType(type, name);

/* Only filter attributes that can be assigned to strings or primitives */
if (attributeClass.isPrimitive() || String.class.isAssignableFrom(attributeClass)) {
params.add(new QueryParameter()
.type("string")
.name("filter[" + typeName + "." + name + "][" + op.getNotation() + "]")
.description("Filters the collection of " + typeName + " by the attribute "
+ name + " " + "using the operator " + op.getNotation()));
}
});
}
}

return params;
Expand Down Expand Up @@ -605,6 +613,8 @@ private boolean lineageContainsType(PathMetaData other) {
*/
public SwaggerBuilder(EntityDictionary dictionary, Info info) {
this.dictionary = dictionary;
this.supportLegacyDialect = true;
this.supportRSQLDialect = true;
globalResponses = new HashMap<>();
globalParams = new HashSet<>();
allClasses = new HashSet<>();
Expand Down Expand Up @@ -636,6 +646,26 @@ public SwaggerBuilder withGlobalResponse(int code, Response response) {
return this;
}

/**
* Turns on or off the legacy filter dialect.
* @param enableLegacyDialect Whether or not to enable the legacy filter dialect.
* @return the builder
*/
public SwaggerBuilder withLegacyFilterDialect(boolean enableLegacyDialect) {
supportLegacyDialect = enableLegacyDialect;
return this;
}

/**
* Turns on or off the RSQL filter dialect.
* @param enableRSQLDialect Whether or not to enable the RSQL filter dialect.
* @return the builder
*/
public SwaggerBuilder withRSQLFilterDialect(boolean enableRSQLDialect) {
supportRSQLDialect = enableRSQLDialect;
return this;
}

/**
* Decorates every path with the given parameter.
* @param param the parameter to decorate
Expand Down
Expand Up @@ -600,6 +600,83 @@ class NothingToSort {
assertEquals(sortValues, ((StringProperty) sortParam.getItems()).getEnum());
}

@Test
public void testAllFilterParameters() throws Exception {
Info info = new Info()
.title("Test Service");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
Swagger swagger = builder.build();

Operation op = swagger.getPaths().get("/book").getGet();

List<String> paramNames = op.getParameters().stream()
.filter(param -> param.getName().startsWith("filter"))
.map(Parameter::getName)
.sorted()
.collect(Collectors.toList());

List<String> expectedNames = Arrays.asList("filter", "filter[book.title][ge]", "filter[book.title][gt]",
"filter[book.title][in]", "filter[book.title][infix]", "filter[book.title][isnull]",
"filter[book.title][le]", "filter[book.title][lt]", "filter[book.title][not]",
"filter[book.title][notnull]", "filter[book.title][postfix]", "filter[book.title][prefix]",
"filter[book.year][ge]", "filter[book.year][gt]", "filter[book.year][in]", "filter[book.year][infix]",
"filter[book.year][isnull]", "filter[book.year][le]", "filter[book.year][lt]", "filter[book.year][not]",
"filter[book.year][notnull]", "filter[book.year][postfix]", "filter[book.year][prefix]",
"filter[book]");

assertEquals(expectedNames, paramNames);
}

@Test
public void testRsqlOnlyFilterParameters() throws Exception {
Info info = new Info()
.title("Test Service");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
builder = builder.withLegacyFilterDialect(false);
Swagger swagger = builder.build();

Operation op = swagger.getPaths().get("/book").getGet();

List<String> paramNames = op.getParameters().stream()
.filter(param -> param.getName().startsWith("filter"))
.map(Parameter::getName)
.sorted()
.collect(Collectors.toList());

List<String> expectedNames = Arrays.asList("filter", "filter[book]");

assertEquals(expectedNames, paramNames);
}

@Test
public void testLegacyOnlyFilterParameters() throws Exception {
Info info = new Info()
.title("Test Service");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
builder = builder.withRSQLFilterDialect(false);
Swagger swagger = builder.build();

Operation op = swagger.getPaths().get("/book").getGet();

List<String> paramNames = op.getParameters().stream()
.filter(param -> param.getName().startsWith("filter"))
.map(Parameter::getName)
.sorted()
.collect(Collectors.toList());

List<String> expectedNames = Arrays.asList("filter[book.title][ge]", "filter[book.title][gt]",
"filter[book.title][in]", "filter[book.title][infix]", "filter[book.title][isnull]",
"filter[book.title][le]", "filter[book.title][lt]", "filter[book.title][not]",
"filter[book.title][notnull]", "filter[book.title][postfix]", "filter[book.title][prefix]",
"filter[book.year][ge]", "filter[book.year][gt]", "filter[book.year][in]", "filter[book.year][infix]",
"filter[book.year][isnull]", "filter[book.year][le]", "filter[book.year][lt]", "filter[book.year][not]",
"filter[book.year][notnull]", "filter[book.year][postfix]", "filter[book.year][prefix]");

assertEquals(expectedNames, paramNames);
}

/**
* Verifies that the given property is of type 'Data' containing a reference to the given model.
Expand Down
Expand Up @@ -40,7 +40,7 @@ public Map<String, Swagger> provide() {
dictionary.bindEntity(Publisher.class);
Info info = new Info().title("Test Service").version("1.0");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
SwaggerBuilder builder = new SwaggerBuilder(dictionary, info).withLegacyFilterDialect(false);
Swagger swagger = builder.build();

Map<String, Swagger> docs = new HashMap<>();
Expand Down
Expand Up @@ -41,7 +41,7 @@ public Map<String, Swagger> enableSwagger() {
dictionary.bindEntity(Comment.class);
Info info = new Info().title("Test Service").version("1.0");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
SwaggerBuilder builder = new SwaggerBuilder(dictionary, info).withLegacyFilterDialect(false);
Swagger swagger = builder.build();

Map<String, Swagger> docs = new HashMap<>();
Expand Down
Expand Up @@ -116,7 +116,7 @@ public Swagger buildSwagger(EntityDictionary dictionary, ElideConfigProperties s
.title(settings.getSwagger().getName())
.version(settings.getSwagger().getVersion());

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
SwaggerBuilder builder = new SwaggerBuilder(dictionary, info).withLegacyFilterDialect(false);

Swagger swagger = builder.build().basePath(settings.getJsonApi().getPath());

Expand Down
Expand Up @@ -75,7 +75,7 @@ public Map<String, Swagger> enableSwagger() {
dictionary.bindEntity(Post.class);
Info info = new Info().title("Test Service").version("1.0");

SwaggerBuilder builder = new SwaggerBuilder(dictionary, info);
SwaggerBuilder builder = new SwaggerBuilder(dictionary, info).withLegacyFilterDialect(false);
Swagger swagger = builder.build();

Map<String, Swagger> docs = new HashMap<>();
Expand Down

0 comments on commit bd51647

Please sign in to comment.