Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ default <T> boolean containsAll(Function<E, T> toValue, Collection<T> values) {
*/
@TerminalOp(canBeUndefined = true, mustBeArray = true)
default <T> boolean contains(Function<E, T> toValue, Predicate<T> test) {
return count(toValue, test) > 0;
return stream().anyMatch(e -> test.test(toValue.apply(e)));
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/org/hisp/dhis/jsontree/JsonVirtualTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,11 @@ private static List<Property> componentProperties(Class<? extends Record> of) {
.map(
c ->
{
Class<? extends JsonValue> jsonType = Validation.NodeType.toJsonType(c.getType());
return new Property(
of,
Text.of(c.getName()),
jsonType,
Validation.NodeType.ofJsonType(jsonType),
Validation.NodeType.toJsonType(c.getType()),
Validation.NodeType.of(c.getType()),
c.getName(),
c.getAnnotatedType(),
c);
Expand Down Expand Up @@ -541,7 +540,7 @@ private static List<Property> captureProperties(Class<? extends JsonObject> of)
in,
name,
type,
Validation.NodeType.ofJsonType(type),
Validation.NodeType.of(type),
method.getName(),
method.getAnnotatedReturnType(),
method));
Expand Down
30 changes: 25 additions & 5 deletions src/main/java/org/hisp/dhis/jsontree/Validation.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,33 @@ public static NodeType of(@CheckNull JsonNodeType type) {
@NotNull
@SuppressWarnings("unchecked")
public static Set<NodeType> of(@NotNull Class<?> type) {
return ofJsonType(
JsonValue.class.isAssignableFrom(type)
? (Class<? extends JsonValue>) type
: toJsonType(type));
if (type.isAnnotationPresent(Validation.class)) {
Validation validation = type.getAnnotation(Validation.class);
NodeType[] types = validation.type();
if (types.length > 0) return EnumSet.of(types[0], types);
}
if (JsonValue.class.isAssignableFrom(type))
return ofJsonType((Class<? extends JsonValue>) type);
return ofJsonType(toJsonType(type));
}

static Class<? extends JsonValue> toJsonType(Class<?> type) {
if (type.isAnnotationPresent(Validation.class)) {
Validation validation = type.getAnnotation(Validation.class);
NodeType[] types = validation.type();
if (types.length == 1) {
return switch (types[0]) {
case INTEGER -> JsonInteger.class;
case BOOLEAN -> JsonBoolean.class;
case ARRAY -> JsonArray.class;
case STRING -> JsonString.class;
case OBJECT -> JsonObject.class;
case NUMBER -> JsonNumber.class;
case NULL -> JsonValue.class;
};
}
if (types.length > 1) return JsonMixed.class;
}
if (type == String.class || type.isEnum()) return JsonString.class;
if (type == Character.class || type == char.class) return JsonString.class;
if (type == Class.class) return JsonString.class;
Expand All @@ -194,7 +214,7 @@ static Class<? extends JsonValue> toJsonType(Class<?> type) {
}

@SuppressWarnings("unchecked")
static Set<NodeType> ofJsonType(Class<? extends JsonValue> type) {
private static Set<NodeType> ofJsonType(Class<? extends JsonValue> type) {
Validation validation = type.getAnnotation(Validation.class);
if (validation != null) {
NodeType[] types = validation.type();
Expand Down
24 changes: 24 additions & 0 deletions src/test/java/org/hisp/dhis/jsontree/JsonNodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,19 @@
*/
package org.hisp.dhis.jsontree;

import static org.hisp.dhis.jsontree.JsonNode.Index.ADD;
import static org.hisp.dhis.jsontree.JsonNode.Index.AUTO;
import static org.hisp.dhis.jsontree.JsonNode.Index.AUTO_SKIP;
import static org.hisp.dhis.jsontree.JsonNode.Index.CHECK;
import static org.hisp.dhis.jsontree.JsonNode.Index.SKIP;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;

import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -266,6 +271,25 @@ void testGetListener_AbstractMethod_DoesExist() {
assertEquals(".bar", rec.getLast().toString());
}

@Test
void testIndexResolve() {
// AUTO on tree keeps the operation level
assertEquals(SKIP, SKIP.resolve(AUTO));
assertEquals(SKIP, AUTO_SKIP.resolve(AUTO));
assertEquals(CHECK, CHECK.resolve(AUTO));
assertEquals(ADD, ADD.resolve(AUTO));
assertEquals(AUTO, AUTO.resolve(AUTO));

// but if something else is set on tree level AUTO(_SKIP) becomes that strategy
for (JsonNode.Index strategy : List.of(SKIP, CHECK, ADD, AUTO_SKIP)) {
assertEquals(SKIP, SKIP.resolve(strategy));
assertEquals(strategy, AUTO_SKIP.resolve(strategy));
assertEquals(CHECK, CHECK.resolve(strategy));
assertEquals(ADD, ADD.resolve(strategy));
assertEquals(strategy, AUTO.resolve(strategy));
}
}

private static void assertGetThrowsJsonPathException(String json, String path, String expected) {
JsonNode root = JsonNode.of(json);
JsonPathException ex = assertThrowsExactly(JsonPathException.class, () -> root.get(path));
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/org/hisp/dhis/jsontree/JsonObjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import java.util.Set;

import org.hisp.dhis.jsontree.JsonNode.Index;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -150,4 +151,17 @@ void testProject() {
assertTrue(obj.has("a", "b"));
assertFalse(obj.has("a", "b", "c"));
}

@Validation(type = Validation.NodeType.INTEGER)
record Id(String value) {}
record Container(Id id) {}

@Test
void testProperties_NodeTypeOverride() {
List<JsonObject.Property> properties = JsonObject.properties(Container.class);
JsonObject.Property id = properties.get(0);
assertEquals(Set.of(Validation.NodeType.INTEGER), id.types());
assertEquals(JsonInteger.class, id.jsonType());
assertEquals(new Container(new Id("12")), JsonMixed.of("{\"id\": 12}").to(Container.class));
}
}
Loading