io.openapiprocessor.jsonschema.schema.Bucket Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of json-schema-validator Show documentation
Show all versions of json-schema-validator Show documentation
OpenAPI Parser JSON-Schema Validator
/*
* Copyright 2021 https://github.com/openapi-processor/openapi-parser
* PDX-License-Identifier: Apache-2.0
*/
package io.openapiprocessor.jsonschema.schema;
import io.openapiprocessor.jsonschema.converter.*;
import io.openapiprocessor.jsonschema.support.Types;
import io.openapiprocessor.jsonschema.support.Uris;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static io.openapiprocessor.jsonschema.support.Null.nonNull;
/**
* wraps the properties {@link Map} of a json/yaml object and its location in the source document.
*/
public class Bucket {
private final Scope scope;
private final JsonPointer location;
private final Map properties;
public static Bucket empty() {
return createBucket(Scope.empty(), Collections.emptyMap());
}
public static @Nullable Bucket createBucket(Scope scope, @Nullable Object source) {
if (!Types.isObject (source)) {
return null;
}
return new Bucket (scope, Types.asObject (source));
}
public static @Nullable Bucket createBucket(Scope scope, @Nullable Object source, JsonPointer location) {
if (!Types.isObject (source)) {
return null;
}
return new Bucket (scope, location, Types.asObject (source));
}
public static Bucket createBucket(Scope scope, Map source) {
return new Bucket (scope, Types.asObject (source));
}
/**
* create a document "root" bucket with an empty location.
*
* @param scope the scope of the document
* @param properties the document properties
*/
public Bucket (Scope scope, Map properties) {
this.scope = scope;
this.location = JsonPointer.empty();
this.properties = properties;
}
/**
* create an object bucket with scope & location in the source document and its properties.
*
* @param scope the scope of the bucket
* @param location the location (json pointer) inside {@code source}
* @param properties the document properties
*/
public Bucket (Scope scope, JsonPointer location, Map properties) {
this.scope = scope;
this.location = location;
this.properties = properties;
}
/**
* create an object bucket with the object location in the source document and its properties.
*
* @param scope the document scope
* @param location the location (json pointer) inside {@code source}
* @param properties the document properties
*/
public Bucket (Scope scope, String location, Map properties) {
this.scope = scope;
this.location = JsonPointer.from (location);
this.properties = properties;
}
/**
* the scope of this bucket.
*
* @return the document {@link URI}
*/
public Scope getScope () {
return scope;
}
public URI getBaseUri () {
return scope.getBaseUri ();
}
public boolean hasId () {
return scope.getVersion ().getIdProvider ().getId (properties) != null;
}
public @Nullable URI getId () {
String id = scope.getVersion ().getIdProvider ().getId (properties);
if (id == null)
return null;
return Uris.createUri (id);
}
/**
* the location of this bucket in the {@code source} document.
*
* @return the location
*/
public JsonPointer getLocation () {
return location;
}
/**
* convert the property value to the expected type.
*
* @param property property name
* @param converter property converter
* @param target type
* @return a {@code T} object or null
*/
public @Nullable T convert (String property, PropertyConverter converter) {
return converter.convert (property, getRawValue (property), getLocation (property));
}
/**
* convert "this" bucket to the expected type.
*
* @param converter properties converter
* @param target type
* @return a {@code T} object or null
*/
public @Nullable T convert (PropertiesConverter converter) {
return converter.convert (properties, location.toString ());
}
/**
* get property value as a {@code Bucket}. Throws if the property value is not an object
* properties {@link Map}.
*
* @param property property name
* @return child bucket
*/
public @Nullable Bucket getBucket (String property) {
Object value = getRawValue (property);
if (value == null)
return null;
if (!Types.isMap (value))
throw new TypeMismatchException (getLocation (property), Map.class);
return new Bucket (scope, getLocation (property), Types.asMap (value));
}
/**
* get the raw value of the given property.
*
* @param property property name
* @return property value or null if the property does not exist
*/
public @Nullable Object getRawValue (String property) {
return properties.get (property);
}
/**
* get the raw value, i.e. the property map, of the bucket.
*
* @return the property map
*/
public Map getRawValues () {
return properties;
}
/**
* checks if properties contains the given property name.
*
* @param property property name
* @return true if the property exists, else false
*/
public boolean hasProperty (String property) {
return properties.containsKey (property);
}
public @Nullable Object getProperty (String property) {
return properties.get (property);
}
/**
* get the raw value at the given property pointer position.
*
* @param pointer property location
* @return property value or null if the property does not exist
*/
// @Deprecated // replace with getRawValueX
// public @Nullable Object getRawValue (JsonPointer pointer) {
// JsonPointer current = JsonPointer.EMPTY;
// Object value = properties;
//
// for (String token: pointer.getTokens ()) {
// current = current.append (token);
//
// if (isObject (value)) {
// value = getObjectValue (asMap (value), current);
//
// } else if (isArray (value)) {
// value = getArrayValue (asCol (value), current);
// }
// }
//
// return value;
// }
/**
* get the raw value with scope at the given property pointer position.
*
* @param pointer property location
* @return raw value or null if the property does not exist
*/
public @Nullable RawValue getRawValue (JsonPointer pointer) {
JsonPointer current = JsonPointer.empty ();
Object value = properties;
Scope scope = this.scope;
for (String token: pointer.getTokens ()) {
current = current.append (token);
if (value == properties) {
Map self = Types.asObject (value);
value = getObjectValue (self, current);
} else if (Types.isObject (value)) {
Map object = Types.asObject (value);
value = getObjectValue (object, current);
scope = scope.move (value);
} else if (Types.isArray (value)) {
Collection