Skip to content

Commit 43a5ba8

Browse files
Add new QueryCondition interface, add Property condition methods.
- Separate public QueryCondition API from implementation to not expose internal APIs. - PropertyQueryCondition interface to expose alias() method only for property conditions (not for and/or conditions). - Add new Box query method accepting QueryCondition.
1 parent da6359d commit 43a5ba8

File tree

9 files changed

+765
-308
lines changed

9 files changed

+765
-308
lines changed

objectbox-java/src/main/java/io/objectbox/Box.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.lang.reflect.Field;
2020
import java.util.ArrayList;
2121
import java.util.Collection;
22-
import java.util.Collections;
2322
import java.util.HashMap;
2423
import java.util.Iterator;
2524
import java.util.List;
@@ -37,6 +36,7 @@
3736
import io.objectbox.internal.IdGetter;
3837
import io.objectbox.internal.ReflectionCache;
3938
import io.objectbox.query.QueryBuilder;
39+
import io.objectbox.query.QueryCondition;
4040
import io.objectbox.relation.RelationInfo;
4141

4242
/**
@@ -555,6 +555,30 @@ public QueryBuilder<T> query() {
555555
return new QueryBuilder<>(this, store.internalHandle(), store.getDbName(entityClass));
556556
}
557557

558+
/**
559+
* Applies the given query conditions and returns the builder for further customization, such as result order.
560+
* Build the condition using the properties from your entity underscore classes.
561+
* <p>
562+
* An example with a nested OR condition:
563+
* <pre>
564+
* # Java
565+
* box.query(User_.name.equal("Jane")
566+
* .and(User_.age.less(12)
567+
* .or(User_.status.equal("child"))));
568+
*
569+
* # Kotlin
570+
* box.query(User_.name.equal("Jane")
571+
* and (User_.age.less(12)
572+
* or User_.status.equal("child")))
573+
* </pre>
574+
* This method is a shortcut for {@code query().apply(condition)}.
575+
*
576+
* @see QueryBuilder#apply(QueryCondition)
577+
*/
578+
public QueryBuilder<T> query(QueryCondition<T> queryCondition) {
579+
return query().apply(queryCondition);
580+
}
581+
558582
public BoxStore getStore() {
559583
return store;
560584
}

objectbox-java/src/main/java/io/objectbox/Property.java

Lines changed: 191 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,26 @@
1717
package io.objectbox;
1818

1919
import java.io.Serializable;
20-
import java.util.Collection;
20+
import java.util.Date;
2121

2222
import javax.annotation.Nullable;
2323

2424
import io.objectbox.annotation.apihint.Internal;
2525
import io.objectbox.converter.PropertyConverter;
2626
import io.objectbox.exception.DbException;
27-
import io.objectbox.query.QueryCondition;
28-
import io.objectbox.query.QueryCondition.PropertyCondition;
29-
import io.objectbox.query.QueryCondition.PropertyCondition.Operation;
27+
import io.objectbox.query.PropertyQueryCondition;
28+
import io.objectbox.query.PropertyQueryConditionImpl.ByteArrayCondition;
29+
import io.objectbox.query.PropertyQueryConditionImpl.DoubleCondition;
30+
import io.objectbox.query.PropertyQueryConditionImpl.DoubleDoubleCondition;
31+
import io.objectbox.query.PropertyQueryConditionImpl.IntArrayCondition;
32+
import io.objectbox.query.PropertyQueryConditionImpl.LongArrayCondition;
33+
import io.objectbox.query.PropertyQueryConditionImpl.LongCondition;
34+
import io.objectbox.query.PropertyQueryConditionImpl.LongLongCondition;
35+
import io.objectbox.query.PropertyQueryConditionImpl.NullCondition;
36+
import io.objectbox.query.PropertyQueryConditionImpl.StringArrayCondition;
37+
import io.objectbox.query.PropertyQueryConditionImpl.StringCondition;
38+
import io.objectbox.query.PropertyQueryConditionImpl.StringCondition.Operation;
39+
import io.objectbox.query.QueryBuilder.StringOrder;
3040

3141
/**
3242
* Meta data describing a property of an ObjectBox entity.
@@ -90,71 +100,208 @@ public Property(EntityInfo<ENTITY> entity, int ordinal, int id, Class<?> type, S
90100
this.customType = customType;
91101
}
92102

93-
/** Creates an "equal ('=')" condition for this property. */
94-
public QueryCondition eq(Object value) {
95-
return new PropertyCondition(this, Operation.EQUALS, value);
103+
/** Creates an "IS NULL" condition for this property. */
104+
public PropertyQueryCondition<ENTITY> isNull() {
105+
return new NullCondition<>(this, NullCondition.Operation.IS_NULL);
96106
}
97107

98-
/** Creates an "not equal ('&lt;&gt;')" condition for this property. */
99-
public QueryCondition notEq(Object value) {
100-
return new PropertyCondition(this, Operation.NOT_EQUALS, value);
108+
/** Creates an "IS NOT NULL" condition for this property. */
109+
public PropertyQueryCondition<ENTITY> notNull() {
110+
return new NullCondition<>(this, NullCondition.Operation.NOT_NULL);
101111
}
102112

103-
/** Creates an "BETWEEN ... AND ..." condition for this property. */
104-
public QueryCondition between(Object value1, Object value2) {
105-
Object[] values = {value1, value2};
106-
return new PropertyCondition(this, Operation.BETWEEN, values);
113+
/** Creates an "equal ('=')" condition for this property. */
114+
public PropertyQueryCondition<ENTITY> equal(boolean value) {
115+
return new LongCondition<>(this, LongCondition.Operation.EQUAL, value);
107116
}
108117

109-
/** Creates an "IN (..., ..., ...)" condition for this property. */
110-
public QueryCondition in(Object... inValues) {
111-
return new PropertyCondition(this, Operation.IN, inValues);
118+
/** Creates a "not equal ('&lt;&gt;')" condition for this property. */
119+
public PropertyQueryCondition<ENTITY> notEqual(boolean value) {
120+
return new LongCondition<>(this, LongCondition.Operation.NOT_EQUAL, value);
112121
}
113122

114123
/** Creates an "IN (..., ..., ...)" condition for this property. */
115-
public QueryCondition in(Collection<?> inValues) {
116-
return in(inValues.toArray());
124+
public PropertyQueryCondition<ENTITY> oneOf(int[] values) {
125+
return new IntArrayCondition<>(this, IntArrayCondition.Operation.IN, values);
117126
}
118127

119-
/** Creates an "greater than ('&gt;')" condition for this property. */
120-
public QueryCondition gt(Object value) {
121-
return new PropertyCondition(this, Operation.GREATER_THAN, value);
128+
/** Creates a "NOT IN (..., ..., ...)" condition for this property. */
129+
public PropertyQueryCondition<ENTITY> notOneOf(int[] values) {
130+
return new IntArrayCondition<>(this, IntArrayCondition.Operation.NOT_IN, values);
122131
}
123132

124-
/** Creates an "less than ('&lt;')" condition for this property. */
125-
public QueryCondition lt(Object value) {
126-
return new PropertyCondition(this, Operation.LESS_THAN, value);
133+
/** Creates an "equal ('=')" condition for this property. */
134+
public PropertyQueryCondition<ENTITY> equal(long value) {
135+
return new LongCondition<>(this, LongCondition.Operation.EQUAL, value);
127136
}
128137

129-
/** Creates an "IS NULL" condition for this property. */
130-
public QueryCondition isNull() {
131-
return new PropertyCondition(this, Operation.IS_NULL, null);
138+
/** Creates a "not equal ('&lt;&gt;')" condition for this property. */
139+
public PropertyQueryCondition<ENTITY> notEqual(long value) {
140+
return new LongCondition<>(this, LongCondition.Operation.NOT_EQUAL, value);
132141
}
133142

134-
/** Creates an "IS NOT NULL" condition for this property. */
135-
public QueryCondition isNotNull() {
136-
return new PropertyCondition(this, Operation.IS_NOT_NULL, null);
143+
/** Creates a "greater than ('&gt;')" condition for this property. */
144+
public PropertyQueryCondition<ENTITY> greater(long value) {
145+
return new LongCondition<>(this, LongCondition.Operation.GREATER, value);
137146
}
138147

139-
/**
140-
* @see io.objectbox.query.QueryBuilder#contains(Property, String)
141-
*/
142-
public QueryCondition contains(String value) {
143-
return new PropertyCondition(this, Operation.CONTAINS, value);
148+
/** Creates a "less than ('&lt;')" condition for this property. */
149+
public PropertyQueryCondition<ENTITY> less(long value) {
150+
return new LongCondition<>(this, LongCondition.Operation.LESS, value);
144151
}
145152

146-
/**
147-
* @see io.objectbox.query.QueryBuilder#startsWith(Property, String)
148-
*/
149-
public QueryCondition startsWith(String value) {
150-
return new PropertyCondition(this, Operation.STARTS_WITH, value);
153+
/** Creates an "IN (..., ..., ...)" condition for this property. */
154+
public PropertyQueryCondition<ENTITY> oneOf(long[] values) {
155+
return new LongArrayCondition<>(this, LongArrayCondition.Operation.IN, values);
156+
}
157+
158+
/** Creates a "NOT IN (..., ..., ...)" condition for this property. */
159+
public PropertyQueryCondition<ENTITY> notOneOf(long[] values) {
160+
return new LongArrayCondition<>(this, LongArrayCondition.Operation.NOT_IN, values);
161+
}
162+
163+
/** Creates an "BETWEEN ... AND ..." condition for this property. */
164+
public PropertyQueryCondition<ENTITY> between(long lowerBoundary, long upperBoundary) {
165+
return new LongLongCondition<>(this, LongLongCondition.Operation.BETWEEN, lowerBoundary, upperBoundary);
151166
}
152167

153168
/**
154-
* @see io.objectbox.query.QueryBuilder#endsWith(Property, String)
169+
* Calls {@link #between(double, double)} with {@code value - tolerance} as lower bound and
170+
* {@code value + tolerance} as upper bound.
155171
*/
156-
public QueryCondition endsWith(String value) {
157-
return new PropertyCondition(this, Operation.ENDS_WITH, value);
172+
public PropertyQueryCondition<ENTITY> equal(double value, double tolerance) {
173+
return new DoubleDoubleCondition<>(this, DoubleDoubleCondition.Operation.BETWEEN,
174+
value - tolerance, value + tolerance);
175+
}
176+
177+
/** Creates a "greater than ('&gt;')" condition for this property. */
178+
public PropertyQueryCondition<ENTITY> greater(double value) {
179+
return new DoubleCondition<>(this, DoubleCondition.Operation.GREATER, value);
180+
}
181+
182+
/** Creates a "less than ('&lt;')" condition for this property. */
183+
public PropertyQueryCondition<ENTITY> less(double value) {
184+
return new DoubleCondition<>(this, DoubleCondition.Operation.LESS, value);
185+
}
186+
187+
/** Creates an "BETWEEN ... AND ..." condition for this property. */
188+
public PropertyQueryCondition<ENTITY> between(double lowerBoundary, double upperBoundary) {
189+
return new DoubleDoubleCondition<>(this, DoubleDoubleCondition.Operation.BETWEEN,
190+
lowerBoundary, upperBoundary);
191+
}
192+
193+
/** Creates an "equal ('=')" condition for this property. */
194+
public PropertyQueryCondition<ENTITY> equal(Date value) {
195+
return new LongCondition<>(this, LongCondition.Operation.EQUAL, value);
196+
}
197+
198+
/** Creates a "not equal ('&lt;&gt;')" condition for this property. */
199+
public PropertyQueryCondition<ENTITY> notEqual(Date value) {
200+
return new LongCondition<>(this, LongCondition.Operation.NOT_EQUAL, value);
201+
}
202+
203+
/** Creates a "greater than ('&gt;')" condition for this property. */
204+
public PropertyQueryCondition<ENTITY> greater(Date value) {
205+
return new LongCondition<>(this, LongCondition.Operation.GREATER, value);
206+
}
207+
208+
/** Creates a "less than ('&lt;')" condition for this property. */
209+
public PropertyQueryCondition<ENTITY> less(Date value) {
210+
return new LongCondition<>(this, LongCondition.Operation.LESS, value);
211+
}
212+
213+
/** Creates an "BETWEEN ... AND ..." condition for this property. */
214+
public PropertyQueryCondition<ENTITY> between(Date lowerBoundary, Date upperBoundary) {
215+
return new LongLongCondition<>(this, LongLongCondition.Operation.BETWEEN, lowerBoundary, upperBoundary);
216+
}
217+
218+
/** Creates an "equal ('=')" condition for this property. */
219+
public PropertyQueryCondition<ENTITY> equal(String value) {
220+
return new StringCondition<>(this, StringCondition.Operation.EQUAL, value);
221+
}
222+
223+
/** Creates an "equal ('=')" condition for this property. */
224+
public PropertyQueryCondition<ENTITY> equal(String value, StringOrder order) {
225+
return new StringCondition<>(this, StringCondition.Operation.EQUAL, value, order);
226+
}
227+
228+
/** Creates a "not equal ('&lt;&gt;')" condition for this property. */
229+
public PropertyQueryCondition<ENTITY> notEqual(String value) {
230+
return new StringCondition<>(this, StringCondition.Operation.NOT_EQUAL, value);
231+
}
232+
233+
/** Creates a "not equal ('&lt;&gt;')" condition for this property. */
234+
public PropertyQueryCondition<ENTITY> notEqual(String value, StringOrder order) {
235+
return new StringCondition<>(this, StringCondition.Operation.NOT_EQUAL, value, order);
236+
}
237+
238+
/** Creates a "greater than ('&gt;')" condition for this property. */
239+
public PropertyQueryCondition<ENTITY> greater(String value) {
240+
return new StringCondition<>(this, StringCondition.Operation.GREATER, value);
241+
}
242+
243+
/** Creates a "greater than ('&gt;')" condition for this property. */
244+
public PropertyQueryCondition<ENTITY> greater(String value, StringOrder order) {
245+
return new StringCondition<>(this, StringCondition.Operation.GREATER, value, order);
246+
}
247+
248+
/** Creates a "less than ('&lt;')" condition for this property. */
249+
public PropertyQueryCondition<ENTITY> less(String value) {
250+
return new StringCondition<>(this, StringCondition.Operation.LESS, value);
251+
}
252+
253+
/** Creates a "less than ('&lt;')" condition for this property. */
254+
public PropertyQueryCondition<ENTITY> less(String value, StringOrder order) {
255+
return new StringCondition<>(this, StringCondition.Operation.LESS, value, order);
256+
}
257+
258+
public PropertyQueryCondition<ENTITY> contains(String value) {
259+
return new StringCondition<>(this, StringCondition.Operation.CONTAINS, value);
260+
}
261+
262+
public PropertyQueryCondition<ENTITY> contains(String value, StringOrder order) {
263+
return new StringCondition<>(this, StringCondition.Operation.CONTAINS, value, order);
264+
}
265+
266+
public PropertyQueryCondition<ENTITY> startsWith(String value) {
267+
return new StringCondition<>(this, Operation.STARTS_WITH, value);
268+
}
269+
270+
public PropertyQueryCondition<ENTITY> startsWith(String value, StringOrder order) {
271+
return new StringCondition<>(this, Operation.STARTS_WITH, value, order);
272+
}
273+
274+
public PropertyQueryCondition<ENTITY> endsWith(String value) {
275+
return new StringCondition<>(this, Operation.ENDS_WITH, value);
276+
}
277+
278+
public PropertyQueryCondition<ENTITY> endsWith(String value, StringOrder order) {
279+
return new StringCondition<>(this, Operation.ENDS_WITH, value, order);
280+
}
281+
282+
/** Creates an "IN (..., ..., ...)" condition for this property. */
283+
public PropertyQueryCondition<ENTITY> oneOf(String[] values) {
284+
return new StringArrayCondition<>(this, StringArrayCondition.Operation.IN, values);
285+
}
286+
287+
/** Creates an "IN (..., ..., ...)" condition for this property. */
288+
public PropertyQueryCondition<ENTITY> oneOf(String[] values, StringOrder order) {
289+
return new StringArrayCondition<>(this, StringArrayCondition.Operation.IN, values, order);
290+
}
291+
292+
/** Creates an "equal ('=')" condition for this property. */
293+
public PropertyQueryCondition<ENTITY> equal(byte[] value) {
294+
return new ByteArrayCondition<>(this, ByteArrayCondition.Operation.EQUAL, value);
295+
}
296+
297+
/** Creates a "greater than ('&gt;')" condition for this property. */
298+
public PropertyQueryCondition<ENTITY> greater(byte[] value) {
299+
return new ByteArrayCondition<>(this, ByteArrayCondition.Operation.GREATER, value);
300+
}
301+
302+
/** Creates a "less than ('&lt;')" condition for this property. */
303+
public PropertyQueryCondition<ENTITY> less(byte[] value) {
304+
return new ByteArrayCondition<>(this, ByteArrayCondition.Operation.LESS, value);
158305
}
159306

160307
@Internal
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package io.objectbox.query;
2+
3+
/**
4+
* Logic based query conditions, currently {@link AndCondition} and {@link OrCondition}.
5+
*/
6+
abstract class LogicQueryCondition<T> extends QueryConditionImpl<T> {
7+
8+
private final QueryConditionImpl<T> leftCondition;
9+
private final QueryConditionImpl<T> rightCondition;
10+
11+
LogicQueryCondition(QueryConditionImpl<T> leftCondition, QueryConditionImpl<T> rightCondition) {
12+
this.leftCondition = leftCondition;
13+
this.rightCondition = rightCondition;
14+
}
15+
16+
@Override
17+
void apply(QueryBuilder<T> builder) {
18+
leftCondition.apply(builder);
19+
long leftConditionPointer = builder.internalGetLastCondition();
20+
21+
rightCondition.apply(builder);
22+
long rightConditionPointer = builder.internalGetLastCondition();
23+
24+
applyOperator(builder, leftConditionPointer, rightConditionPointer);
25+
}
26+
27+
abstract void applyOperator(QueryBuilder<T> builder, long leftCondition, long rightCondition);
28+
29+
/**
30+
* Combines the left condition using AND with the right condition.
31+
*/
32+
static class AndCondition<T> extends LogicQueryCondition<T> {
33+
34+
AndCondition(QueryConditionImpl<T> leftCondition, QueryConditionImpl<T> rightCondition) {
35+
super(leftCondition, rightCondition);
36+
}
37+
38+
@Override
39+
void applyOperator(QueryBuilder<T> builder, long leftCondition, long rightCondition) {
40+
builder.internalAnd(leftCondition, rightCondition);
41+
}
42+
}
43+
44+
/**
45+
* Combines the left condition using OR with the right condition.
46+
*/
47+
static class OrCondition<T> extends LogicQueryCondition<T> {
48+
49+
OrCondition(QueryConditionImpl<T> leftCondition, QueryConditionImpl<T> rightCondition) {
50+
super(leftCondition, rightCondition);
51+
}
52+
53+
@Override
54+
void applyOperator(QueryBuilder<T> builder, long leftCondition, long rightCondition) {
55+
builder.internalOr(leftCondition, rightCondition);
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)