OData Query Builder in Java for Java Applications v 0.0.4
Inspired by Jared Mahan An eloquently fluent OData query builder for NPM
Use Maven
<dependencies>
<dependency>
<groupId>io.github.habeebcycle</groupId>
<artifactId>o-data-query-builder</artifactId>
<version>0.0.4</version>
</dependency>
...
</dependencies>
or Gradle
implementation group: 'io.github.habeebcycle', name: 'o-data-query-builder', version: '0.0.4'
or
implementation 'io.github.habeebcycle:o-data-query-builder:0.0.4'
String query = new QueryBuilder()
.count()
.top(5)
.skip(5)
.expand("MyProps")
.orderBy("MyProp2")
.filter(f -> f.filterExpression("Property", EQ, "MyValue"))
.select("Field1,Field2")
.toQuery();
Outputs:
?$orderby=MyProp2&$top=5&$skip=5&$count=true&$expand=MyProps&$select=Field1,Field2&$filter=Property eq 'MyValue'
Filter expressions utilize logical operators to filter data on a specific property.
Operator Options, changed in version 0.0.2 and above:
- Equal:
eq
-FilterExpression.EQ
- Not Equal:
ne
-FilterExpression.NE
- Greater Than:
gt
-FilterExpression.GT
- Greater Than or Equal:
ge
-FilterExpression.GE
- Less Than:
lt
-FilterExpression.LT
- Less Than or Equal:
le
-FilterExpression.LE
Operator Options, version 0.0.1:
- Equal:
eq
-FilterExpression.EQUALS
- Not Equal:
ne
-FilterExpression.NOT_EQUALS
- Greater Than:
gt
-FilterExpression.GREATER_THAN
- Greater Than or Equal:
ge
-FilterExpression.GREATER_THAN_EQUAL
- Less Than:
lt
-FilterExpression.LESS_THAN
- Less Than or Equal:
le
-FilterExpression.LESS_THAN_EQUAL
String query = new QueryBuilder()
.filter(f -> f.filterExpression("Property1", EQ, "Value1"))
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1'
You can also combine filter expressions in version 0.0.2 and above:
String[] values = {"value1", "value2"}; // or you can pass a list: List.of("value1", "value2")
String query = new QueryBuilder()
.filter(f -> f.filterExpressions("Property1", FilterExpression.EQ, values)).toQuery();
Outputs: ?$filter=Property1 eq 'value1' and Property1 eq 'value2'
Filter phrases are to be used with canonical functions. Filter Phrasing exposes the filter as a string which allows you to inject any of the various filtering mechanisms available in OData v4
.
Below are a few examples:
String query = new QueryBuilder()
.filter(f ->
f.filterPhrase(FilterPhrases.contains("Property1","Value1"))
.filterPhrase(FilterPhrases.startsWith("Property1","Value1"))
.filterPhrase(FilterPhrases.endsWith("Property1","Value1"))
.filterPhrase(FilterPhrases.indexOf("Property1","Value1", EQ, 1))
.filterPhrase(FilterPhrases.length("Property1", EQ, 19))
.filterPhrase(FilterPhrases.substring("Property1", 1, 2, EQ, "ab"))
).toQuery();
Outputs: ?$filter=contains(Property1,'Value1') and startswith(Property1,'Value1') and endswith(Property1,'Value1') and indexof(Property1,'Value1') eq 1 and length(Property1) eq 19 and substring(Property1, 1, 2) eq 'ab'
You can also combine filter phrases in version 0.0.2 and above:
List<String> phrases = List.of("startswith(Property1,'Value1')", "contains(Property1,'Value1')", "length(Property1) eq 19"); //you can also pass an array new String[]{"startswith(Property1,'Value1')", "length(Property1) eq 19"}
String query = new QueryBuilder()
.filter(f -> f.filterPhrases(phrases)).toQuery();
Outputs: ?$filter=startswith(Property1,'Value1') and contains(Property1,'Value1') and length(Property1) eq 19
By default, when you utilize .filter
you are using the and
operator. You can be explicit by passing your operator into the filter as a secondary parameter.
String query = new QueryBuilder().filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value1"),
AND)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' and Property2 eq 'Value1'
String query = new QueryBuilder()
.filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value2"),
AND)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' and Property2 eq 'Value2'
String query = new QueryBuilder()
.filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value2"),
OR)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' or Property2 eq 'Value2'
Nested or grouped filtering is used when we need to write a more complex filter for a data set. This can be done by utilizing .and()
or .or()
with the filter.
String query = new QueryBuilder()
.filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value2")
.and(f1 -> f1 //can be - 'or'
.filterExpression("Property3", EQ, "Value3")
.filterExpression("Property4", EQ, "Value4")
)
)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' and Property2 eq 'Value2' and (Property3 eq 'Value3' and Property4 eq 'Value4')
String query = new QueryBuilder()
.filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value2")
.or(f1 -> f1 //can be - 'and'
.filterExpression("Property3", EQ, "Value3")
.filterExpression("Property4", EQ, "Value4")
)
)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' and Property2 eq 'Value2' and (Property3 eq 'Value3' or Property4 eq 'Value4')
Reminder: We can still explicitly control the conditional operators within each of the filters by utilizing the filter's condition operator parameter which gives us even more control over the filter.
String query6 = new QueryBuilder()
.filter(f -> f
.filterExpression("Property1", EQ, "Value1")
.filterExpression("Property2", EQ, "Value2")
.and(f1 -> f1 //can be - 'or'
.filterExpression("Property3", EQ, "Value3")
.filterExpression("Property4", EQ, "Value4")
),
AND //can be - "or"
)
.toQuery();
Outputs: ?$filter=Property1 eq 'Value1' and Property2 eq 'Value2' and (Property3 eq 'Value3' or Property4 eq 'Value4')