Skip to content

Commit

Permalink
Reviewed task. Deleting unused method and adjusted some formatting.
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 Jun 7, 2018
1 parent 71a8601 commit c7687b3
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 118 deletions.
69 changes: 30 additions & 39 deletions json/src/main/java/org/eclipse/ditto/json/ImmutableJsonObject.java
Expand Up @@ -315,53 +315,44 @@ public JsonObject get(final JsonFieldSelector fieldSelector) {

if (isEmpty()) {
return this;
} else {
final List<JsonPointer> pointersContainedInThis = fieldSelector.getPointers()
.stream()
.filter(this::contains)
.collect(Collectors.toList());
if (pointersContainedInThis.isEmpty()) {
return JsonFactory.newObject();
} else {
return filterByTree(this, JsonFieldSelectorTrie.of(pointersContainedInThis));
}
}
}

/*
* Build a JsonFieldSelectorTrie ignoring all pointers not contained in this object.
*/
private JsonFieldSelectorTrie trieOfPointersContainedInThis(final Iterable<JsonPointer> jsonPointers) {
final JsonFieldSelectorTrie trie = new JsonFieldSelectorTrie();
jsonPointers.forEach(jsonPointer -> {
if (contains(jsonPointer)) {
trie.add(jsonPointer);
}
});
return trie;
final List<JsonPointer> pointersContainedInThis = fieldSelector.getPointers()
.stream()
.filter(this::contains)
.collect(Collectors.toList());

if (pointersContainedInThis.isEmpty()) {
return JsonFactory.newObject();
} else {
return filterByTrie(this, JsonFieldSelectorTrie.of(pointersContainedInThis));
}
}

@SuppressWarnings("unchecked")
private static JsonObject filterByTree(final JsonObject me, final JsonFieldSelectorTrie trie) {
private static JsonObject filterByTrie(final JsonObject self, final JsonFieldSelectorTrie trie) {
if (trie.isEmpty()) {
return me;
} else {
final JsonObjectBuilder builder = JsonFactory.newObjectBuilder();
trie.getKeys().forEach(key -> {
me.getField(key).ifPresent(child -> {
final JsonValue filteredChild = child.getValue().isObject()
? filterByTree(child.getValue().asObject(), trie.descend(key))
: child.getValue();
final Optional<JsonFieldDefinition> childFieldDefinition = child.getDefinition();
if (childFieldDefinition.isPresent()) {
builder.set(childFieldDefinition.get(), filteredChild);
} else {
builder.set(key, filteredChild);
}
});
return self;
}

final JsonObjectBuilder builder = JsonFactory.newObjectBuilder();

for (final JsonKey key : trie.getKeys()) {
self.getField(key).ifPresent(child -> {
final JsonValue childValue = child.getValue();
final JsonValue filteredChildValue = childValue.isObject()
? filterByTrie(childValue.asObject(), trie.descend(key))
: childValue;
final Optional<JsonFieldDefinition> childFieldDefinition = child.getDefinition();
if (childFieldDefinition.isPresent()) {
builder.set(childFieldDefinition.get(), filteredChildValue);
} else {
builder.set(key, filteredChildValue);
}
});
return builder.build();
}

return builder.build();
}

@Override
Expand Down
46 changes: 22 additions & 24 deletions json/src/main/java/org/eclipse/ditto/json/JsonFieldDefinition.java
Expand Up @@ -19,8 +19,10 @@
* A {@code JsonFieldDefinition} is a formal description of a single {@link JsonField}. A JSON field consists of a key
* (or name) and a value. A JsonFieldDefinition differs in the way that it consists not only of a simple JSON key but
* its super type {@link JsonPointer}. With the help of this interface one can explicitly define a schema of a JSON
* document including all sub documents. <p> The following example shows how a JSON document would be described with the
* help of JsonFieldDefinition.
* document including all sub documents.
* <p>
* The following example shows how a JSON document would be described with the help of JsonFieldDefinition.
* </p>
* <p>
* <pre>
* {
Expand All @@ -35,31 +37,35 @@
* </pre>
* <p>
* Within an according class the structure of this JSON document could be described as follows:
* </p>
* <p>
* <pre>
* import static JsonFactory.newFieldDefinition;
* ...
* import static JsonFactory.newIntFieldDefinition;
* import static JsonFactory.newStringFieldDefinition;
* ...
*
* public final class Thing {
* public final class Thing {
*
* private static final JsonFieldDefinition THING_ID = newFieldDefinition("thingId", String.class);
* private static final JsonFieldDefinition SUBSEL = newFieldDefinition("attributes/someAttr/subsel",
* int.class);
* private static final JsonFieldDefinition ANOTHER_ATTR = newFieldDefinition("attributes/anotherAttr",
* String.class);
* private static final JsonFieldDefinition THING_ID = newStringFieldDefinition("thingId");
* private static final JsonFieldDefinition SUBSEL = newIntFieldDefinition("attributes/someAttr/subsel");
* private static final JsonFieldDefinition ANOTHER_ATTR = newStringFieldDefinition("attributes/anotherAttr");
*
* ...
* ...
*
* }
* }
* </pre>
* </p>
* <p>
* In this case {@code attributes} and {@code someAttr} are implicitly defined with the value type {@link JsonObject}.
* </p>
* <p>
* Additionally, a JSON field definition can be marked with zero to n {@link JsonFieldMarker}s. The semantics of a
* marker is defined by you rather than Ditto JSON. One possible usage scenario would be to define the fields which
* belong to a particular schema version with a maker according to that version.
* </p>
* <p>
* <em>Implementations of this interface are required to be immutable!</em>
* </p>
*/
public interface JsonFieldDefinition<T> {

Expand Down Expand Up @@ -134,9 +140,7 @@ static JsonFieldDefinition<Double> ofDouble(final CharSequence pointer, final Js
* @throws IllegalArgumentException if {@code pointer} is empty.
* @see JsonFactory#newBooleanFieldDefinition(CharSequence, JsonFieldMarker...)
*/
static JsonFieldDefinition<Boolean> ofBoolean(final CharSequence pointer,
final JsonFieldMarker ... markers) {

static JsonFieldDefinition<Boolean> ofBoolean(final CharSequence pointer, final JsonFieldMarker ... markers) {
return JsonFactory.newBooleanFieldDefinition(pointer, markers);
}

Expand All @@ -151,9 +155,7 @@ static JsonFieldDefinition<Boolean> ofBoolean(final CharSequence pointer,
* @throws IllegalArgumentException if {@code pointer} is empty.
* @see JsonFactory#newJsonObjectFieldDefinition(CharSequence, JsonFieldMarker...)
*/
static JsonFieldDefinition<JsonObject> ofJsonObject(final CharSequence pointer,
final JsonFieldMarker ... markers) {

static JsonFieldDefinition<JsonObject> ofJsonObject(final CharSequence pointer, final JsonFieldMarker ... markers) {
return JsonFactory.newJsonObjectFieldDefinition(pointer, markers);
}

Expand All @@ -168,9 +170,7 @@ static JsonFieldDefinition<JsonObject> ofJsonObject(final CharSequence pointer,
* @throws IllegalArgumentException if {@code pointer} is empty.
* @see JsonFactory#newJsonArrayFieldDefinition(CharSequence, JsonFieldMarker...)
*/
static JsonFieldDefinition<JsonArray> ofJsonArray(final CharSequence pointer,
final JsonFieldMarker ... markers) {

static JsonFieldDefinition<JsonArray> ofJsonArray(final CharSequence pointer, final JsonFieldMarker ... markers) {
return JsonFactory.newJsonArrayFieldDefinition(pointer, markers);
}

Expand All @@ -185,9 +185,7 @@ static JsonFieldDefinition<JsonArray> ofJsonArray(final CharSequence pointer,
* @throws IllegalArgumentException if {@code pointer} is empty.
* @see JsonFactory#newJsonValueFieldDefinition(CharSequence, JsonFieldMarker...)
*/
static JsonFieldDefinition<JsonValue> ofJsonValue(final CharSequence pointer,
final JsonFieldMarker ... markers) {

static JsonFieldDefinition<JsonValue> ofJsonValue(final CharSequence pointer, final JsonFieldMarker ... markers) {
return JsonFactory.newJsonValueFieldDefinition(pointer, markers);
}

Expand Down
Expand Up @@ -11,6 +11,8 @@
*/
package org.eclipse.ditto.json;

import static java.util.Objects.requireNonNull;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
Expand All @@ -23,11 +25,11 @@
* a {@code JsonObject} by, since it requires no merging of sub-objects.
* <p>
* A normal {@code JsonFieldSelector} is a list of {@code JsonPointer}s, for example:
* <pre>{@code
* JsonPointer_1: a -> b -> c -> d
* JsonPoniter_2: a -> b -> e
* JsonPointer_3: b -> b -> c
* }</pre>
* <pre>
* JsonPointer 1: a -> b -> c -> d
* JsonPointer 2: a -> b -> e
* JsonPointer 3: b -> b -> c
* </pre>
* {@code JsonFieldSelectorTrie} represents the list as trie by collecting lists with the same prefix:
* <pre>{@code
*
Expand All @@ -53,54 +55,37 @@ final class JsonFieldSelectorTrie {
/**
* Children of the trie.
*/
private final Map<JsonKey, JsonFieldSelectorTrie> children = new HashMap<>();
private final Map<JsonKey, JsonFieldSelectorTrie> children;

/**
* @return whether this trie has any child.
*/
boolean isEmpty() {
return children.isEmpty();
private JsonFieldSelectorTrie() {
children = new HashMap<>();
}

/**
* @return set of labels of children.
*/
Set<JsonKey> getKeys() {
return children.keySet();
}

/**
* retrieve a child.
* Creates a trie from the specified JsonPointers.
*
* @param key label of the child.
* @return the child if it exists; an empty trie if it does not.
* @param jsonPointers collection of JSON pointers which form the returned trie.
* @return trie representation of the collection.
* @throws NullPointerException if {@code jsonPointers} is {@code null}.
*/
JsonFieldSelectorTrie descend(final JsonKey key) {
final JsonFieldSelectorTrie child = children.get(key);
return child != null ? child : new JsonFieldSelectorTrie();
static JsonFieldSelectorTrie of(final Iterable<JsonPointer> jsonPointers) {
requireNonNull(jsonPointers, "The JSON pointers must not be null!");

final JsonFieldSelectorTrie trie = new JsonFieldSelectorTrie();
jsonPointers.forEach(trie::add);
return trie;
}

/**
* Mutate the trie minimally so that the path of JsonKeys in the JsonPointer exists in the trie.
* Mutates the trie minimally so that the path of JsonKeys in the JsonPointer exists in the trie.
*
* @param jsonPointer the path to expand.
* @return this trie after adding the path in json pointer.
* @return this trie after adding the path in JSON pointer.
* @throws NullPointerException if {@code jsonPointer} is {@code null}.
*/
JsonFieldSelectorTrie add(final JsonPointer jsonPointer) {
final Iterator<JsonKey> iterator = jsonPointer.iterator();
return addJsonKeyIterator(iterator);
}

/**
* Create a trie from a collection of JsonPointers.
*
* @param jsonPointers collection of json pointers.
* @return trie representation of the collection.
*/
static JsonFieldSelectorTrie of(final Iterable<JsonPointer> jsonPointers) {
final JsonFieldSelectorTrie trie = new JsonFieldSelectorTrie();
jsonPointers.forEach(trie::add);
return trie;
requireNonNull(jsonPointer, "The JSON pointer to be added must not be null!");
return addJsonKeyIterator(jsonPointer.iterator());
}

/**
Expand All @@ -120,4 +105,34 @@ private JsonFieldSelectorTrie addJsonKeyIterator(final Iterator<JsonKey> iterato
}
return this;
}

/**
* Indicates whether this trie has any child.
*
* @return {@code true} if this trie has a child, {@code false} else.
*/
boolean isEmpty() {
return children.isEmpty();
}

/**
* Returns the keys of the children.
*
* @return the keys.
*/
Set<JsonKey> getKeys() {
return children.keySet();
}

/**
* Retrieves a child.
*
* @param key label of the child.
* @return the child if it exists; an empty trie if it does not.
*/
JsonFieldSelectorTrie descend(final JsonKey key) {
final JsonFieldSelectorTrie child = children.get(key);
return child != null ? child : new JsonFieldSelectorTrie();
}

}
Expand Up @@ -114,7 +114,7 @@ public void orderOfFieldsDoesNotAffectEquality() {

@Test(expected = NullPointerException.class)
public void tryToGetInstanceFromNullJsonObject() {
ImmutableJsonObject.of((Map<String, JsonField>) null);
ImmutableJsonObject.of(null);
}

@Test
Expand Down Expand Up @@ -193,7 +193,7 @@ public void setWorksAsExpected() {
@Test(expected = NullPointerException.class)
public void tryToSetIntValueWithNullKey() {
final JsonObject underTest = ImmutableJsonObject.empty();
underTest.setValue((String) null, KNOWN_INT_23);
underTest.setValue(null, KNOWN_INT_23);
}

@Test
Expand Down Expand Up @@ -409,8 +409,10 @@ public void setValueWithJsonPointerToExistingJsonObject() {
final JsonObject bazJsonObject = ImmutableJsonObject.of(toMap("baz", KNOWN_INT_23));

final int intValue10 = 10;
final JsonObject barJsonObject =
JsonFactory.newObjectBuilder().set("bar", bazJsonObject).set("yo", intValue10).build();
final JsonObject barJsonObject = JsonFactory.newObjectBuilder()
.set("bar", bazJsonObject)
.set("yo", intValue10)
.build();

final JsonObject underTest = ImmutableJsonObject.of(toMap("foo", barJsonObject));

Expand Down Expand Up @@ -537,7 +539,7 @@ public void getValueWithPointerFromJsonObjectWithJsonArrayAtSomePointerLevel() {
@Test(expected = NullPointerException.class)
public void tryToRemoveJsonFieldByNullName() {
final JsonObject underTest = ImmutableJsonObject.of(KNOWN_FIELDS);
underTest.remove((String) null);
underTest.remove(null);
}

@Test
Expand Down Expand Up @@ -570,9 +572,9 @@ public void removingExistingJsonFieldByNameReturnsDisjunctJsonObject() {
underTest.remove(KNOWN_KEY_BAZ);

assertThat(afterRemoval)
.contains(KNOWN_KEY_BAZ, KNOWN_VALUE_BAZ)
.as("Another removal on original"
+ " JSON object has no influence on the JSON object which was created after first removal.");
+ " JSON object has no influence on the JSON object which was created after first removal.")
.contains(KNOWN_KEY_BAZ, KNOWN_VALUE_BAZ);
}

@Test
Expand Down Expand Up @@ -1272,8 +1274,7 @@ public void shouldHandleOverlappingFieldSelectors() {
final JsonObject underTest = JsonFactory.newObject(jsonString);

// a field selector is overlapping if one pointer is a prefix of another.
final JsonFieldSelector overlappingSelector =
JsonFieldSelector.newInstance("x/y", "x/z", "x");
final JsonFieldSelector overlappingSelector = JsonFieldSelector.newInstance("x/y", "x/z", "x");
final JsonObject actual = underTest.get(overlappingSelector);

assertThat(actual).isEqualTo(underTest.remove("w"));
Expand Down
Expand Up @@ -23,7 +23,7 @@
/**
* Unit test for {@link JsonFieldSelectorTrie}.
*/
public class JsonFieldSelectorTrieTest {
public final class JsonFieldSelectorTrieTest {

@Test
public void trieWithEmptyPathIsEmpty() {
Expand Down Expand Up @@ -59,4 +59,5 @@ private static Set<JsonKey> getDescendantKeys(final JsonFieldSelectorTrie trie,
return trie.getKeys();
}
}

}

0 comments on commit c7687b3

Please sign in to comment.