Skip to content
This repository has been archived by the owner on May 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3 from indeedeng/Ecwidgh-213-indeed
Browse files Browse the repository at this point in the history
url-encode filter parameter
  • Loading branch information
ovesh authored Oct 21, 2021
2 parents bf9c635 + c0d69a2 commit a16c5e8
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 34 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ artifacts {

group = "com.indeed"
archivesBaseName = "consul-api"
version = "1.4.8"
version = "1.4.9"

def doUploadArchives = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')
if (doUploadArchives) {
Expand Down
25 changes: 24 additions & 1 deletion src/main/java/com/ecwid/consul/v1/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ public enum MatchingOperator {
NOT_MATCHES("not matches", false);

private final String representation;
private final String encoded;
private final boolean unary;

MatchingOperator(final String representation, final boolean unary) {
this.representation = representation;
encoded = representation.replaceAll(" ", SPACE);
this.unary = unary;
}

Expand Down Expand Up @@ -138,7 +140,7 @@ public Filter not() {

@Override
public List<String> toUrlParameters() {
return Collections.singletonList("filter=" + toString());
return Collections.singletonList("filter=" + toEncodedString());
}

@Override
Expand Down Expand Up @@ -181,6 +183,27 @@ public String toString() {
return prefix + "(" + result + ")";
}

private static final String SPACE = "%20";
private static final String DOUBLEQUOTE = "%22";

public String toEncodedString() {
final String prefix = positive ? "" : ("not" + SPACE);
if (leaf == null) {
final String result = children.stream().map(Filter::toEncodedString).collect(Collectors.joining(SPACE + boolOp + SPACE));
if ((parent == null) && positive) {
return result;
}
return prefix + "(" + result + ")";
}
if (leaf.value == null) {
return prefix + leaf.selector + SPACE + leaf.matchingOperator.encoded;
}
if ((leaf.matchingOperator == MatchingOperator.IN) || (leaf.matchingOperator == MatchingOperator.NOT_IN)) {
return prefix + DOUBLEQUOTE + leaf.value + DOUBLEQUOTE + SPACE + leaf.matchingOperator.encoded + SPACE + leaf.selector;
}
return prefix + leaf.selector + SPACE + leaf.matchingOperator.encoded + SPACE + DOUBLEQUOTE + leaf.value + DOUBLEQUOTE;
}

private enum BoolOp {
OR("or"),
AND("and");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public String getNear() {

/**
* @deprecated use {@link HealthServicesRequest.Builder#setFilter(Filter)} to filter by tags
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.tags")))}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.Tags")))}
*/
@Deprecated
public String getTag() {
Expand All @@ -89,7 +89,7 @@ public String getTag() {

/**
* @deprecated use {@link HealthServicesRequest.Builder#setFilter(Filter)} to filter by tags
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.tags")))}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.Tags")))}
*/
@Deprecated
public String[] getTags() {
Expand Down Expand Up @@ -146,7 +146,7 @@ public Builder setNear(String near) {

/**
* @deprecated use {@link #setFilter(Filter)}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.tags")))}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.Tags")))}
*/
@Deprecated
public Builder setTag(String tag) {
Expand All @@ -156,7 +156,7 @@ public Builder setTag(String tag) {

/**
* @deprecated use {@link #setFilter(Filter)}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.tags")))}
* e.g {@code * setFilter(Filter.in(tag, Filter.Selector.of("Service.Tags")))}
*/
@Deprecated
public Builder setTags(String[] tags) {
Expand Down
62 changes: 34 additions & 28 deletions src/test/java/com/ecwid/consul/v1/FilterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,60 +32,60 @@ void shouldVerify() {
@Test
public void of() {
Filter actual = Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo"), "bar");
assertEquals("foo = \"bar\"", actual.toString());
assertFilter("foo = \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.NOT_EQUAL, Selector.of("foo"), "bar");
assertEquals("foo != \"bar\"", actual.toString());
assertFilter("foo != \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.NOT_EQUAL, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.IS_EMPTY, Selector.of("foo"), null);
assertEquals("foo is empty", actual.toString());
assertFilter("foo is empty", actual);
actual = Filter.of(Filter.MatchingOperator.IS_EMPTY, Selector.of("foo"));
assertEquals("foo is empty", actual.toString());
assertFilter("foo is empty", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.IS_EMPTY, Selector.of("foo"), "bar"));

actual = Filter.of(Filter.MatchingOperator.IS_NOT_EMPTY, Selector.of("foo"), null);
assertEquals("foo is not empty", actual.toString());
assertFilter("foo is not empty", actual);
actual = Filter.of(Filter.MatchingOperator.IS_NOT_EMPTY, Selector.of("foo"));
assertEquals("foo is not empty", actual.toString());
assertFilter("foo is not empty", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.IS_NOT_EMPTY, Selector.of("foo"), "bar"));

actual = Filter.of(Filter.MatchingOperator.IN, Selector.of("foo"), "bar");
assertEquals("\"bar\" in foo", actual.toString());
assertFilter("\"bar\" in foo", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.IN, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.NOT_IN, Selector.of("foo"), "bar");
assertEquals("\"bar\" not in foo", actual.toString());
assertFilter("\"bar\" not in foo", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.NOT_IN, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.CONTAINS, Selector.of("foo"), "bar");
assertEquals("foo contains \"bar\"", actual.toString());
assertFilter("foo contains \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.CONTAINS, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.NOT_CONTAINS, Selector.of("foo"), "bar");
assertEquals("foo not contains \"bar\"", actual.toString());
assertFilter("foo not contains \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.NOT_CONTAINS, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.MATCHES, Selector.of("foo"), "bar");
assertEquals("foo matches \"bar\"", actual.toString());
assertFilter("foo matches \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.MATCHES, Selector.of("foo")));

actual = Filter.of(Filter.MatchingOperator.NOT_MATCHES, Selector.of("foo"), "bar");
assertEquals("foo not matches \"bar\"", actual.toString());
assertFilter("foo not matches \"bar\"", actual);
assertThrows(IllegalArgumentException.class, ()-> Filter.of(Filter.MatchingOperator.NOT_MATCHES, Selector.of("foo")));
}

@Test
public void in() {
final Filter actual = Filter.in("bar", Selector.of("foo"));
assertEquals("\"bar\" in foo", actual.toString());
assertFilter("\"bar\" in foo", actual);
}

@Test
public void notIn() {
final Filter actual = Filter.notIn("bar", Selector.of("foo"));
assertEquals("\"bar\" not in foo", actual.toString());
assertFilter("\"bar\" not in foo", actual);
}

@Test
Expand All @@ -96,15 +96,15 @@ public void and() {
Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo2"), "bar2")
);

assertEquals("foo = \"bar\" and foo1 = \"bar1\" and foo2 = \"bar2\"", actual.toString());
assertFilter("foo = \"bar\" and foo1 = \"bar1\" and foo2 = \"bar2\"", actual);

final Filter actual2 = f
.or(Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo1"), "bar1"))
.and(Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo3"), "bar3"));
assertEquals("(foo = \"bar\" or foo1 = \"bar1\") and foo3 = \"bar3\"", actual2.toString());
assertFilter("(foo = \"bar\" or foo1 = \"bar1\") and foo3 = \"bar3\"", actual2);

final Filter actual3 = f.and();
assertEquals("foo = \"bar\"", actual3.toString());
assertFilter("foo = \"bar\"", actual3);
}

@Test
Expand All @@ -114,7 +114,7 @@ public void addAll() {
Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo1"), "bar1")
}
));
assertEquals("foo = \"bar\" and foo1 = \"bar1\"", actual.toString());
assertFilter("foo = \"bar\" and foo1 = \"bar1\"", actual);
}

@Test
Expand All @@ -125,15 +125,15 @@ public void or() {
Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo2"), "bar2")
);

assertEquals("foo = \"bar\" or foo1 = \"bar1\" or foo2 = \"bar2\"", actual.toString());
assertFilter("foo = \"bar\" or foo1 = \"bar1\" or foo2 = \"bar2\"", actual);

final Filter actual2 = f
.and(Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo1"), "bar1"))
.or(Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo3"), "bar3"));
assertEquals("(foo = \"bar\" and foo1 = \"bar1\") or foo3 = \"bar3\"", actual2.toString());
assertFilter("(foo = \"bar\" and foo1 = \"bar1\") or foo3 = \"bar3\"", actual2);

final Filter actual3 = f.or();
assertEquals("foo = \"bar\"", actual3.toString());
assertFilter("foo = \"bar\"", actual3);
}

@Test
Expand All @@ -143,25 +143,31 @@ public void orAll() {
Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo1"), "bar1")
}
));
assertEquals("foo = \"bar\" or foo1 = \"bar1\"", actual.toString());
assertFilter("foo = \"bar\" or foo1 = \"bar1\"", actual);
}

@Test
public void not() {
final Filter f = Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo"), "bar");
assertEquals("foo = \"bar\"", f.toString());
assertEquals("not foo = \"bar\"", f.not().toString());
assertEquals("foo = \"bar\"", f.not().not().toString());
assertFilter("foo = \"bar\"", f);
assertFilter("not foo = \"bar\"", f.not());
assertFilter("foo = \"bar\"", f.not().not());

final Filter f2 = f.and(Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo1"), "bar2"));
assertEquals("foo = \"bar\" and foo1 = \"bar2\"", f2.toString());
assertEquals("not (foo = \"bar\" and foo1 = \"bar2\")", f2.not().toString());
assertFilter("foo = \"bar\" and foo1 = \"bar2\"", f2);
assertFilter("not (foo = \"bar\" and foo1 = \"bar2\")", f2.not());
}

@Test
public void toUrlParameters() {
final Filter subject = Filter.of(Filter.MatchingOperator.EQUAL, Selector.of("foo"), "bar");
final List<String> actual = subject.toUrlParameters();
assertEquals(Collections.singletonList("filter=foo = \"bar\""), actual);
assertEquals(Collections.singletonList("filter=foo%20=%20%22bar%22"), actual);
}

private void assertFilter(final String expected, final Filter subject) {
assertEquals(expected, subject.toString());
final String encoded = expected.replaceAll(" ", "%20").replaceAll("\"", "%22");
assertEquals(encoded, subject.toEncodedString());
}
}

0 comments on commit a16c5e8

Please sign in to comment.