Skip to content

Commit

Permalink
perf: probing access without exception, cache MethodHandles (#66)
Browse files Browse the repository at this point in the history
* perf: skip while without predicate to allow inline

* perf: cache default method handles

* perf: cache used MethodHandles

* test: adds unit tests
  • Loading branch information
jbee authored Aug 9, 2024
1 parent 0fbc271 commit 9fe29dc
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 163 deletions.
87 changes: 67 additions & 20 deletions src/main/java/org/hisp/dhis/jsontree/JsonNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/
package org.hisp.dhis.jsontree;

import org.hisp.dhis.jsontree.internal.Maybe;
import org.hisp.dhis.jsontree.internal.Surly;

import java.io.IOException;
Expand Down Expand Up @@ -250,42 +251,56 @@ default JsonNode getParent() {
* @throws JsonPathException when no such node exists in the subtree of this node
*/
@Surly
default JsonNode get(@Surly String path )
throws JsonPathException {
default JsonNode get(@Surly String path ) throws JsonPathException {
if ( path.isEmpty() ) return this;
if ( "$".equals( path ) ) return getRoot();
if ( path.startsWith( "$" ) ) return getRoot().get( path.substring( 1 ) );
if (!path.startsWith( "{" ) && !path.startsWith( "[" ) && !path.startsWith( "." ))
path = "."+path;
char c0 = path.charAt( 0 );
if ( c0 == '$' ) return getRoot().get( path.substring( 1 ) );
if ( c0 != '{' && c0 != '[' && c0 != '.' ) path = "."+path;
return get( JsonPath.of( path ) );
}

/**
* Access the node at the given path in the subtree of this node.
*
* @param path a simple or nested path relative to this node. A path starting with {@code $} is relative to the root
* node of this node, in other words it is an absolute path
* @return the node at the given path or {@code null} if no such node exists
* @throws JsonPathException when the provided path is malformed
* @since 1.5
*/
@Maybe
default JsonNode getOrNull(@Surly String path ) throws JsonPathException {
if ( path.isEmpty() ) return this;
if ( "$".equals( path ) ) return getRoot();
char c0 = path.charAt( 0 );
if ( c0 == '$' ) return getRoot().getOrNull( path.substring( 1 ) );
if ( c0 != '{' && c0 != '[' && c0 != '.' ) path = "."+path;
return getOrNull( JsonPath.of( path ) );
}

/**
* @param path a path understood relative to this node's {@link #getPath()}
* @return the node at the given path
* @throws JsonPathException when no such node exists in the subtree of this node
* @since 1.1
*/
@Surly
default JsonNode get(@Surly JsonPath path) {
default JsonNode get(@Surly JsonPath path) throws JsonPathException {
throw new JsonPathException( path,
format( "This is a leaf node of type %s that does not have any children at path: %s", getType(), path ) );
}

/**
* Access node by path with default.
*
* @param path a simple or nested path relative to this node
* @param orDefault value to return in no node at the given path exist in this subtree
* @return the node at path or the provided default if no such node exists
* @since 1.1
* @param path a path understood relative to this node's {@link #getPath()}
* @return the node at the given path or {@code null} if no such node exists
* @throws JsonPathException when the provided path is malformed
* @since 1.5
*/
default JsonNode getOrDefault( String path, JsonNode orDefault ) {
try {
return get( path );
} catch ( JsonPathException ex ) {
return orDefault;
}
@Maybe
default JsonNode getOrNull(@Surly JsonPath path) throws JsonPathException {
throw new JsonPathException( path,
format( "This is a leaf node of type %s that does not have any children at path: %s", getType(), path ) );
}

/**
Expand Down Expand Up @@ -332,7 +347,7 @@ default boolean isRoot() {
*/
default boolean isMember( String name ) {
try {
return member( name ) != null;
return memberOrNull( name ) != null;
} catch ( JsonPathException ex ) {
return false;
}
Expand All @@ -347,7 +362,7 @@ default boolean isMember( String name ) {
*/
default boolean isElement( int index ) {
try {
return element( index ) != null;
return elementOrNull( index ) != null;
} catch ( JsonPathException ex ) {
return false;
}
Expand Down Expand Up @@ -379,11 +394,27 @@ default boolean isElement( int index ) {
* @throws JsonPathException when no such member exists
* @throws JsonTreeException if this node is not an object node that could have members
*/
@Surly
default JsonNode member( String name )
throws JsonPathException {
throw new JsonTreeException( getType() + " node has no member property: " + name );
}

/**
* OBS! Only defined when this node is of type {@link JsonNodeType#OBJECT}).
*
* @param name name of the member to access
* @return the member with the given name or {@code null} if no such member exists
* @throws JsonPathException when the path is malformed
* @throws JsonTreeException if this node is not an object node that could have members
* @since 1.5
*/
@Maybe
default JsonNode memberOrNull( String name )
throws JsonPathException {
throw new JsonTreeException( getType() + " node has no member property: " + name );
}

/**
* OBS! Only defined when this node is of type {@link JsonNodeType#OBJECT}).
* <p>
Expand Down Expand Up @@ -463,11 +494,27 @@ default Iterator<Entry<String, JsonNode>> members( boolean cacheNodes ) {
* @throws JsonPathException when no such element exists
* @throws JsonTreeException if this node is not an array node that could have elements
*/
@Surly
default JsonNode element( int index )
throws JsonPathException {
throw new JsonTreeException( getType() + " node has no element property for index: " + index );
}

/**
* OBS! Only defined when this node is of type {@link JsonNodeType#ARRAY}).
*
* @param index index of the element to access
* @return the node at the given array index or {@code null} if no such element exists
* @throws JsonPathException when the index is negative (invalid)
* @throws JsonTreeException if this node is not an array node that could have elements
* @since 1.5
*/
@Maybe
default JsonNode elementOrNull( int index )
throws JsonPathException {
throw new JsonTreeException( getType() + " node has no element property for index: " + index );
}

/**
* OBS! Only defined when this node is of type {@link JsonNodeType#ARRAY}).
* <p>
Expand Down
Loading

0 comments on commit 9fe29dc

Please sign in to comment.