Skip to content

Commit

Permalink
Adjusted code to changes of ditto-json.
Browse files Browse the repository at this point in the history
Signed-off-by: Juergen Fickel <juergen.fickel@bosch-si.com>
  • Loading branch information
Juergen Fickel committed Dec 4, 2018
1 parent 177c09e commit c637493
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 93 deletions.
Expand Up @@ -17,6 +17,7 @@
import java.util.function.Predicate;
import java.util.regex.Pattern;

import org.eclipse.ditto.json.JsonNumber;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.model.query.criteria.visitors.PredicateVisitor;
import org.eclipse.ditto.model.things.Thing;
Expand All @@ -33,7 +34,7 @@ private ThingPredicatePredicateVisitor() {
}

/**
* Gets the singleton instance of this {@link ThingPredicatePredicateVisitor}.
* Gets the singleton instance of this {@code ThingPredicatePredicateVisitor}.
*
* @return the singleton instance.
*/
Expand Down Expand Up @@ -62,7 +63,7 @@ public static Predicate<Thing> apply(
public Function<String, Predicate<Thing>> visitEq(final Object value) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(value::equals)
.isPresent();
}
Expand All @@ -71,7 +72,7 @@ public Function<String, Predicate<Thing>> visitEq(final Object value) {
public Function<String, Predicate<Thing>> visitNe(final Object value) {
return fieldName ->
thing -> !getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(value::equals)
.isPresent();
}
Expand All @@ -80,7 +81,7 @@ public Function<String, Predicate<Thing>> visitNe(final Object value) {
public Function<String, Predicate<Thing>> visitGe(final Object value) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(obj -> obj instanceof Comparable && value instanceof Comparable)
.map(obj -> (Comparable) obj)
.filter(obj -> compare((Comparable) value, obj) >= 0)
Expand All @@ -91,7 +92,7 @@ public Function<String, Predicate<Thing>> visitGe(final Object value) {
public Function<String, Predicate<Thing>> visitGt(final Object value) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(obj -> obj instanceof Comparable && value instanceof Comparable)
.map(obj -> (Comparable) obj)
.filter(obj -> compare((Comparable) value, obj) > 0)
Expand All @@ -102,7 +103,7 @@ public Function<String, Predicate<Thing>> visitGt(final Object value) {
public Function<String, Predicate<Thing>> visitLe(final Object value) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(obj -> obj instanceof Comparable && value instanceof Comparable)
.map(obj -> (Comparable) obj)
.filter(obj -> compare((Comparable) value, obj) <= 0)
Expand All @@ -113,14 +114,14 @@ public Function<String, Predicate<Thing>> visitLe(final Object value) {
public Function<String, Predicate<Thing>> visitLt(final Object value) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(obj -> obj instanceof Comparable && value instanceof Comparable)
.map(obj -> (Comparable) obj)
.filter(obj -> compare((Comparable) value, obj) < 0)
.isPresent();
}

private int compare(final Comparable value, final Comparable obj) {
private static int compare(final Comparable value, final Comparable obj) {
final Comparable comparableObj = asNumber(obj);
final Comparable comparableValue = asNumber(value);
// best effort try to convert both values to a BigDecimal in order to compare them:
Expand Down Expand Up @@ -157,7 +158,7 @@ private static Comparable asNumber(final Comparable comparable) {
public Function<String, Predicate<Thing>> visitIn(final List<?> values) {
return fieldName ->
thing -> getThingField(fieldName, thing)
.map(this::mapJsonValueToJava)
.map(ThingPredicatePredicateVisitor::mapJsonValueToJava)
.filter(values::contains)
.isPresent();
}
Expand All @@ -172,34 +173,35 @@ public Function<String, Predicate<Thing>> visitLike(final String value) {
.isPresent();
}

private Optional<JsonValue> getThingField(final String fieldName, final Thing thing) {
private static Optional<JsonValue> getThingField(final CharSequence fieldName, final Thing thing) {
return thing.toJson(p -> true).getValue(fieldName);
}

private Object mapJsonValueToJava(final JsonValue jsonValue) {
private static Object mapJsonValueToJava(final JsonValue jsonValue) {
final Object result;

if (jsonValue.isString()) {
return jsonValue.asString();
result = jsonValue.asString();
} else if (jsonValue.isBoolean()) {
return jsonValue.asBoolean();
result = jsonValue.asBoolean();
} else if (jsonValue.isNull()) {
return null;
result = null;
} else if (jsonValue.isNumber()) {
final Double doubleValue = jsonValue.asDouble();
if (doubleValue.intValue() == doubleValue) {
// normally we would use intValue here - BUT: the parser always treats numbers as Long
// not producing Integers at all:
return doubleValue.longValue();
} else if (doubleValue.longValue() == doubleValue) {
return doubleValue.longValue();
final JsonNumber jsonNumber = (JsonNumber) jsonValue;
if (jsonNumber.isInt() || jsonNumber.isLong()) {
result = jsonNumber.asLong();
} else {
return doubleValue;
result = jsonNumber.asDouble();
}
} else if (jsonValue.isArray()) {
return null; // filtering arrays is not supported
result = null; // filtering arrays is not supported
} else if (jsonValue.isObject()) {
return null; // filtering objects is not supported
result = null; // filtering objects is not supported
} else {
return null;
result = null;
}

return result;
}

}
Expand Up @@ -10,9 +10,10 @@
*/
package org.eclipse.ditto.model.query.things;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.function.Predicate;

import org.assertj.core.api.Assertions;
import org.eclipse.ditto.json.JsonPointer;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.model.base.headers.DittoHeaders;
Expand All @@ -26,9 +27,9 @@
import org.junit.Test;

/**
* Tests {@link ThingPredicateVisitor}.
* Unit test for {@link ThingPredicateVisitor}.
*/
public class ThingPredicateVisitorTest {
public final class ThingPredicateVisitorTest {

private static final CriteriaFactory criteriaFactory = new CriteriaFactoryImpl();
private static final ThingsFieldExpressionFactory fieldExpressionFactory =
Expand Down Expand Up @@ -110,8 +111,11 @@ private static Predicate<Thing> createPredicate(final String filter) {
return ThingPredicateVisitor.apply(createCriteria(filter));
}

private static void testPredicate(final Thing nonMatchingThing, final String predicate, final String target,
private static void testPredicate(final Thing nonMatchingThing,
final String predicate,
final String target,
final Object value) {

testPredicate(nonMatchingThing, predicate, target, value.toString(), true, false);
}

Expand All @@ -130,20 +134,24 @@ private static void testPredicateNeg(final Thing nonMatchingThing, final String
testPredicate(nonMatchingThing, predicate, target, value, false, true);
}

private static void testPredicate(final Thing nonMatchingThing, final String predicate, final String target,
final String value, final boolean expected, final boolean escapeStr) {
private static void testPredicate(final Thing nonMatchingThing,
final String predicate,
final String target,
final String value,
final boolean expected,
final boolean escapeStr) {

final String stringValue = escapeStr ? "\"" + value + "\"" : value;
final String filter = predicate + "(" + target + "," + stringValue + ")";
final Predicate<Thing> thingPredicate = createPredicate(filter);

Assertions.assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '" + filter + "' with value '" + stringValue + "' should be " +
expected)
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '%s' with value '%s' should be %s", filter, stringValue, expected)
.isEqualTo(expected);

if (nonMatchingThing != null) {
Assertions.assertThat(thingPredicate.test(nonMatchingThing))
.as("Filtering '" + filter + "' with value '" + stringValue + "' should be " + false)
assertThat(thingPredicate.test(nonMatchingThing))
.as("Filtering '%s' with value '%s' should be %s", filter, stringValue, false)
.isFalse();
}
}
Expand Down Expand Up @@ -356,46 +364,46 @@ public void testFilterThingIdWithStringLike() {
@Test
public void testFilterThingIdExists() {
final Predicate<Thing> thingPredicate = createPredicate("exists(thingId)");
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering 'exists(thingId)' should be true")
.isEqualTo(true);
}

@Test
public void testFilterAttributeExists() {
final Predicate<Thing> thingPredicate = createPredicate("exists(attributes/aBoolean)");
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering 'exists(attributes/aBoolean)' should be true")
.isEqualTo(true);

final Predicate<Thing> negativePredicate = createPredicate("exists(attributes/missing)");
Assertions.assertThat(negativePredicate.test(MATCHING_THING))
assertThat(negativePredicate.test(MATCHING_THING))
.as("Filtering 'exists(attributes/missing)' should be false")
.isEqualTo(false);
}

@Test
public void testFilterFeatureExists() {
final Predicate<Thing> thingPredicate = createPredicate("exists(features/foo)");
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering 'exists(features/foo)' should be true")
.isEqualTo(true);

final Predicate<Thing> negativePredicate = createPredicate("exists(features/bar)");
Assertions.assertThat(negativePredicate.test(MATCHING_THING))
assertThat(negativePredicate.test(MATCHING_THING))
.as("Filtering 'exists(features/bar)' should be false")
.isEqualTo(false);
}

@Test
public void testFilterFeaturePropertyExists() {
final Predicate<Thing> thingPredicate = createPredicate("exists(features/foo/properties/aString)");
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering 'exists(features/foo/properties/aString)' should be true")
.isEqualTo(true);

final Predicate<Thing> negativePredicate = createPredicate("exists(features/foo/properties/missing)");
Assertions.assertThat(negativePredicate.test(MATCHING_THING))
assertThat(negativePredicate.test(MATCHING_THING))
.as("Filtering 'exists(features/foo/properties/missing)' should be false")
.isEqualTo(false);
}
Expand All @@ -404,7 +412,7 @@ public void testFilterFeaturePropertyExists() {
public void testLogicalAndWith2queries() {
final String filter = "and(exists(attributes/aBoolean),eq(thingId,\"" + MATCHING_THING_ID + "\"))";
final Predicate<Thing> thingPredicate = createPredicate(filter);
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be true")
.isEqualTo(true);
}
Expand All @@ -417,7 +425,7 @@ public void testLogicalAndWith3queries() {
"gt(attributes/aDouble," + (MATCHING_THING_DOUBLE-0.5) + ")" +
")";
final Predicate<Thing> thingPredicate = createPredicate(filter);
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be true")
.isEqualTo(true);
}
Expand All @@ -426,7 +434,7 @@ public void testLogicalAndWith3queries() {
public void testLogicalOrWith2queries() {
final String filter = "or(exists(attributes/missing),eq(thingId,\"" + MATCHING_THING_ID + "\"))";
final Predicate<Thing> thingPredicate = createPredicate(filter);
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be true")
.isEqualTo(true);
}
Expand All @@ -439,7 +447,7 @@ public void testLogicalOrWith3queries() {
"gt(attributes/aDouble," + (MATCHING_THING_DOUBLE-0.5) + ")" +
")";
final Predicate<Thing> thingPredicate = createPredicate(filter);
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be true")
.isEqualTo(true);
}
Expand All @@ -448,13 +456,13 @@ public void testLogicalOrWith3queries() {
public void testLogicalNotWithEqThingId() {
final String filter = "not(eq(thingId,\"" + MATCHING_THING_ID + "\"))";
final Predicate<Thing> thingPredicate = createPredicate(filter);
Assertions.assertThat(thingPredicate.test(MATCHING_THING))
assertThat(thingPredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be false")
.isEqualTo(false);

final String negativeFilter = "not(eq(thingId,\"" + MATCHING_THING_ID + "-missing" + "\"))";
final Predicate<Thing> negativePredicate = createPredicate(negativeFilter);
Assertions.assertThat(negativePredicate.test(MATCHING_THING))
assertThat(negativePredicate.test(MATCHING_THING))
.as("Filtering '"+ filter + "' should be true")
.isEqualTo(true);
}
Expand Down
Expand Up @@ -271,7 +271,7 @@ public boolean equals(final Object o) {

@Override
public String toString() {
return getClass().getSimpleName() + " [wrapped=" + wrapped + "]";
return wrapped.toString();
}

}
Expand Up @@ -282,7 +282,7 @@ public boolean equals(final Object o) {

@Override
public String toString() {
return getClass().getSimpleName() + " [wrapped=" + wrapped + "]";
return wrapped.toString();
}

}
Expand Up @@ -16,6 +16,7 @@
import java.util.List;

import org.bson.Document;
import org.eclipse.ditto.json.JsonNumber;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.model.things.Attributes;
import org.eclipse.ditto.services.thingsearch.common.util.KeyEscapeUtil;
Expand Down Expand Up @@ -127,7 +128,7 @@ private AttributesDocumentBuilder mainAttribute(final String key, final Object v
}

private void addInternalAttributes(final String path, final JsonValue jsonValue) {
if ((jsonValue == null) || jsonValue.isNull()) {
if (jsonValue == null || jsonValue.isNull()) {
attributeInternally(path, null);
} else if (jsonValue.isString()) {
attributeInternally(path, jsonValue.asString());
Expand All @@ -142,10 +143,11 @@ private void addInternalAttributes(final String path, final JsonValue jsonValue)
}

private void addNumberAttribute(final String path, final JsonValue jsonValue) {
try {
attributeInternally(path, jsonValue.asLong());
} catch (final NumberFormatException e) {
attributeInternally(path, jsonValue.asDouble());
final JsonNumber jsonNumber = (JsonNumber) jsonValue;
if (jsonNumber.isInt() || jsonNumber.isLong()) {
attributeInternally(path, jsonNumber.asLong());
} else {
attributeInternally(path, jsonNumber.asDouble());
}
}

Expand Down
Expand Up @@ -15,6 +15,7 @@

import org.bson.Document;
import org.eclipse.ditto.json.JsonField;
import org.eclipse.ditto.json.JsonNumber;
import org.eclipse.ditto.json.JsonValue;
import org.eclipse.ditto.model.things.Thing;
import org.eclipse.ditto.services.thingsearch.common.util.KeyEscapeUtil;
Expand Down Expand Up @@ -104,11 +105,18 @@ private static Document objectToDocument(final Iterable<JsonField> jsonObject) {
}

private static Object handleNumberAttribute(final JsonValue jsonValue) {
try {
return jsonValue.asLong();
} catch (final NumberFormatException e) {
return jsonValue.asDouble();
final Number result;

final JsonNumber jsonNumber = (JsonNumber) jsonValue;
if (jsonNumber.isInt()) {
result = jsonNumber.asInt();
} else if (jsonNumber.isLong()) {
result = jsonNumber.asLong();
} else {
result = jsonNumber.asDouble();
}

return result;
}

}

0 comments on commit c637493

Please sign in to comment.