All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.networknt.schema.JsonNodePath Maven / Gradle / Ivy

/*
 * Copyright (c) 2023 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.networknt.schema;

import java.util.Objects;

/**
 * Represents a path to a JSON node.
 */
public class JsonNodePath implements Comparable {
    private final PathType type;
    private final JsonNodePath parent;

    private final String pathSegment;
    private final int pathSegmentIndex;

    private volatile String value = null; // computed lazily
    private int hash = 0; // computed lazily

    public JsonNodePath(PathType type) {
        this.type = type;
        this.parent = null;
        this.pathSegment = null;
        this.pathSegmentIndex = -1;
    }

    private JsonNodePath(JsonNodePath parent, String pathSegment) {
        this.parent = parent;
        this.type = parent.type;
        this.pathSegment = pathSegment;
        this.pathSegmentIndex = -1;
    }

    private JsonNodePath(JsonNodePath parent, int pathSegmentIndex) {
        this.parent = parent;
        this.type = parent.type;
        this.pathSegment = null;
        this.pathSegmentIndex = pathSegmentIndex;
    }

    /**
     * Returns the parent path, or null if this path does not have a parent.
     *
     * @return the parent
     */
    public JsonNodePath getParent() {
        return this.parent;
    }

    /**
     * Append the child token to the path.
     *
     * @param token the child token
     * @return the path
     */
    public JsonNodePath append(String token) {
        return new JsonNodePath(this, token);
    }

    /**
     * Append the index to the path.
     * 
     * @param index the index
     * @return the path
     */
    public JsonNodePath append(int index) {
        return new JsonNodePath(this, index);
    }

    /**
     * Gets the {@link PathType}.
     * 
     * @return the path type
     */
    public PathType getPathType() {
        return this.type;
    }

    /**
     * Gets the name element given an index.
     * 

* The index parameter is the index of the name element to return. The element * that is closest to the root has index 0. The element that is farthest from * the root has index count -1. * * @param index to return * @return the name element */ public String getName(int index) { Object element = getElement(index); if (element != null) { return element.toString(); } return null; } /** * Gets the element given an index. *

* The index parameter is the index of the element to return. The element that * is closest to the root has index 0. The element that is farthest from the * root has index count -1. * * @param index to return * @return the element either a String or Integer */ public Object getElement(int index) { if (index == -1) { if (this.pathSegmentIndex != -1) { return this.pathSegmentIndex; } else { return this.pathSegment; } } int nameCount = getNameCount(); if (nameCount - 1 == index) { return this.getElement(-1); } int count = nameCount - index - 1; if (count < 0) { throw new IllegalArgumentException(""); } JsonNodePath current = this; for (int x = 0; x < count; x++) { current = current.parent; } return current.getElement(-1); } /** * Gets the number of name elements in the path. * * @return the number of elements in the path or 0 if this is the root element */ public int getNameCount() { int current = this.pathSegmentIndex == -1 && this.pathSegment == null ? 0 : 1; int parent = this.parent != null ? this.parent.getNameCount() : 0; return current + parent; } /** * Tests if this path starts with the other path. * * @param other the other path * @return true if the path starts with the other path */ public boolean startsWith(JsonNodePath other) { int count = getNameCount(); int otherCount = other.getNameCount(); if (otherCount > count) { return false; } else if (otherCount == count) { return this.equals(other); } else { JsonNodePath compare = this; int x = count - otherCount; while (x > 0) { compare = compare.getParent(); x--; } return other.equals(compare); } } /** * Tests if this path contains a string segment that is an exact match. *

* This will not match if the segment is a number. * * @param segment the segment to test * @return true if the string segment is found */ public boolean contains(String segment) { boolean result = segment.equals(this.pathSegment); if (result) { return true; } JsonNodePath path = this.getParent(); while (path != null) { if (segment.equals(path.pathSegment)) { return true; } path = path.getParent(); } return false; } @Override public String toString() { if (this.value == null) { String parentValue = this.parent == null ? type.getRoot() : this.parent.toString(); if (pathSegmentIndex != -1) { this.value = this.type.append(parentValue, pathSegmentIndex); } else if (pathSegment != null) { this.value = this.type.append(parentValue, pathSegment); } else { this.value = parentValue; } } return this.value; } @Override public int hashCode() { int h = hash; if (h == 0) { h = Objects.hash(parent, pathSegment, pathSegmentIndex, type); hash = h; } return h; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; JsonNodePath other = (JsonNodePath) obj; return Objects.equals(pathSegment, other.pathSegment) && pathSegmentIndex == other.pathSegmentIndex && type == other.type && Objects.equals(parent, other.parent); } @Override public int compareTo(JsonNodePath other) { if (this.parent != null && other.parent == null) { return 1; } else if (this.parent == null && other.parent != null) { return -1; } else if (this.parent != null && other.parent != null) { int result = this.parent.compareTo(other.parent); if (result != 0) { return result; } } String thisValue = this.getName(-1); String otherValue = other.getName(-1); if (thisValue == null && otherValue == null) { return 0; } else if (thisValue != null && otherValue == null) { return 1; } else if (thisValue == null && otherValue != null) { return -1; } else { return thisValue.compareTo(otherValue); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy