Skip to content

Commit ce68c5a

Browse files
authored
feat: object properties as data (#64)
* feat: paths() method to iterate/stream absolute member paths * chore: restart from upstream * feat: object properties as data * refactor: better names and java vs JSON capturing
1 parent e7486e8 commit ce68c5a

14 files changed

+320
-110
lines changed

src/main/java/org/hisp/dhis/jsontree/JsonAbstractArray.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ default E first( Predicate<E> test ) {
121121
* @throws IllegalArgumentException in case the given schema is not an interface
122122
* @since 1.0
123123
*/
124-
default void validateEach(Class<? extends JsonAbstractObject<?>> schema, Rule... rules) {
124+
default void validateEach(Class<? extends JsonObject> schema, Rule... rules) {
125125
forEach( e -> JsonValidator.validate( e, schema, rules ) );
126126
}
127127
}

src/main/java/org/hisp/dhis/jsontree/JsonAbstractCollection.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929

3030
import org.hisp.dhis.jsontree.internal.Surly;
3131

32+
import java.lang.reflect.Method;
33+
import java.util.function.BiConsumer;
34+
import java.util.function.BiPredicate;
35+
3236
import static org.hisp.dhis.jsontree.Validation.NodeType.ARRAY;
3337
import static org.hisp.dhis.jsontree.Validation.NodeType.OBJECT;
3438

@@ -176,6 +180,11 @@ public final <V extends JsonValue> V as( Class<V> as ) {
176180
return viewed.as( as );
177181
}
178182

183+
@Override
184+
public <V extends JsonValue> V as( Class<V> as, BiConsumer<Method, Object[]> onCall ) {
185+
return viewed.as( as, onCall );
186+
}
187+
179188
@Override
180189
public final String toString() {
181190
return viewed.toString();

src/main/java/org/hisp/dhis/jsontree/JsonAbstractObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ default void forEachValue( Consumer<E> action ) {
168168
* @throws IllegalArgumentException in case the given schema is not an interface
169169
* @since 0.11
170170
*/
171-
default void validate( Class<? extends JsonAbstractObject<?>> schema, Rule... rules ) {
171+
default void validate( Class<? extends JsonObject> schema, Rule... rules ) {
172172
JsonValidator.validate( this, schema, rules );
173173
}
174174
}

src/main/java/org/hisp/dhis/jsontree/JsonMixed.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.hisp.dhis.jsontree;
22

3+
import org.hisp.dhis.jsontree.internal.Surly;
4+
35
import java.io.Reader;
46
import java.nio.file.Path;
57

@@ -57,7 +59,7 @@ static JsonMixed of( String json ) {
5759
* {@code null} default mapping is used
5860
* @return root of the virtual tree representing the given JSON input
5961
*/
60-
static JsonMixed of( String json, JsonTypedAccessStore store ) {
62+
static JsonMixed of( String json, @Surly JsonTypedAccessStore store ) {
6163
return new JsonVirtualTree( json, store );
6264
}
6365

src/main/java/org/hisp/dhis/jsontree/JsonObject.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
import org.hisp.dhis.jsontree.Validation.Rule;
3131
import org.hisp.dhis.jsontree.validation.JsonValidator;
3232

33+
import java.lang.reflect.AnnotatedElement;
34+
import java.lang.reflect.AnnotatedType;
3335
import java.util.Collection;
36+
import java.util.List;
3437
import java.util.function.Function;
3538

3639
import static java.util.Arrays.stream;
@@ -48,6 +51,32 @@
4851
@Validation.Ignore
4952
public interface JsonObject extends JsonAbstractObject<JsonValue> {
5053

54+
/**
55+
* An object property based on a default method declared in a type extending {@link JsonObject}.
56+
*
57+
* @param in the {@link JsonObject} type that declared the property
58+
* @param jsonName of the property
59+
* @param jsonType the type the property is resolved to internally when calling {@link #get(String, Class)}
60+
* @param javaName the name of the java property accessed that caused the JSON property to be resolved
61+
* @param javaType the return type of the underlying method that declares the property
62+
* @param source the underlying method that declared the property
63+
* @since 1.4
64+
*/
65+
record Property(Class<? extends JsonObject> in, String jsonName, Class<? extends JsonValue> jsonType,
66+
String javaName, AnnotatedType javaType, AnnotatedElement source) {}
67+
68+
/**
69+
* Note that there can be more than one property with the same {@link Property#javaName()} in case the method it
70+
* reflects accesses more than one member from the JSON object. In such a case each access is a property of the
71+
* accessed {@link Property#jsonName()} with the same {@link Property#javaName()}.
72+
*
73+
* @return a model of this object in form its properties in no particular order
74+
* @since 1.4
75+
*/
76+
static List<Property> properties(Class<? extends JsonObject> of) {
77+
return JsonVirtualTree.properties( of );
78+
}
79+
5180
/**
5281
* Access to object fields by name.
5382
* <p>

src/main/java/org/hisp/dhis/jsontree/JsonTree.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.Map.Entry;
3939
import java.util.NoSuchElementException;
4040
import java.util.Optional;
41+
import java.util.function.BiFunction;
4142
import java.util.function.Consumer;
4243
import java.util.function.Function;
4344
import java.util.function.IntConsumer;

src/main/java/org/hisp/dhis/jsontree/JsonValue.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@
3131
import org.hisp.dhis.jsontree.internal.Surly;
3232

3333
import java.io.Reader;
34+
import java.lang.reflect.AnnotatedElement;
35+
import java.lang.reflect.Method;
36+
import java.lang.reflect.Type;
3437
import java.nio.file.Path;
3538
import java.util.List;
3639
import java.util.Map;
3740
import java.util.Optional;
41+
import java.util.function.BiConsumer;
3842
import java.util.function.BiPredicate;
3943
import java.util.function.Function;
4044
import java.util.function.Predicate;
@@ -110,7 +114,7 @@ static JsonValue of( String json ) {
110114
* {@code null} default mapping is used
111115
* @return virtual JSON tree root {@link JsonValue}
112116
*/
113-
static JsonValue of( String json, JsonTypedAccessStore store ) {
117+
static JsonValue of( String json, @Surly JsonTypedAccessStore store ) {
114118
return json == null || "null".equals( json ) ? JsonVirtualTree.NULL : JsonMixed.of( json, store );
115119
}
116120

@@ -241,6 +245,21 @@ default boolean isBoolean() {
241245
*/
242246
<T extends JsonValue> T as( Class<T> as );
243247

248+
/**
249+
* Same as {@link #as(Class)} but with an additional parameter to pass a callback function. This allows to observe
250+
* the API calls for meta-programming. This should not be used in "normal" API usage.
251+
* <p>
252+
* Not all methods can be observed as some are handled internally without ever going via the proxy. However, in
253+
* contrast to {@link #as(Class)} when using this method any call of a default method is handled via proxy.
254+
*
255+
* @param as assumed value type for this value
256+
* @param onCall a function that is called before the proxy handles an API call that allows to observe calls
257+
* @param <T> value type returned
258+
* @return this object as the provided type, this might mean this object is wrapped as the provided type or
259+
* @since 1.4
260+
*/
261+
<T extends JsonValue> T as( Class<T> as, BiConsumer<Method, Object[]> onCall );
262+
244263
/**
245264
* @return This value as {@link JsonObject} (same as {@code as(JsonObject.class)})
246265
*/

0 commit comments

Comments
 (0)