Skip to content

Commit

Permalink
move back the scope resolution to parser
Browse files Browse the repository at this point in the history
  • Loading branch information
redmitry committed Aug 27, 2024
1 parent aa69121 commit e094457
Show file tree
Hide file tree
Showing 28 changed files with 242 additions and 237 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import es.elixir.bsc.json.schema.model.impl.AbstractJsonSchemaElement;
import es.elixir.bsc.json.schema.model.impl.JsonMultitypeSchemaWrapper;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
Expand Down Expand Up @@ -84,7 +85,7 @@ public AbstractJsonSchema parse(JsonSchemaLocator locator, AbstractJsonSchemaEle

if (value.getValueType() == ValueType.TRUE ||
value.getValueType() == ValueType.FALSE) {
return new BooleanJsonSchemaImpl(parent, locator, jsonPointer).read(this, value);
return new BooleanJsonSchemaImpl(parent, locator, locator, jsonPointer).read(this, value);
}

if (value.getValueType() != ValueType.OBJECT) {
Expand All @@ -103,10 +104,12 @@ public AbstractJsonSchema parse(JsonSchemaLocator locator, AbstractJsonSchemaEle

// before draft 2019-09 $ref ignored any other properties
if (JsonSchemaVersion.SCHEMA_DRAFT_2019_09.compareTo(getJsonSchemaVersion(locator)) > 0) {
return new JsonReferenceImpl(parent, locator, jsonPointer).read(this, object);
return new JsonReferenceImpl(parent, locator, locator, jsonPointer).read(this, object);
}
}


final JsonSchemaLocator scope = getScope(locator, object);

final JsonValue type_value = object.get(TYPE);
final ValueType vtype;
if (type_value == null) {
Expand Down Expand Up @@ -135,29 +138,29 @@ public AbstractJsonSchema parse(JsonSchemaLocator locator, AbstractJsonSchemaEle
if (jenum.isEmpty()) {
throw new JsonSchemaException(new ParsingError(ParsingMessage.EMPTY_ENUM));
}
return new JsonEnumImpl(parent, locator, jsonPointer).read(this, object);
return new JsonEnumImpl(parent, scope, locator, jsonPointer).read(this, object);
}

final JsonValue jconst = object.get(CONST);
if (jconst != null) {
return new JsonConstImpl(parent, locator, jsonPointer).read(this, object);
return new JsonConstImpl(parent, scope, locator, jsonPointer).read(this, object);
}

if (type == null) {
return new JsonMultitypeSchemaWrapper(parent, locator, jsonPointer,
return new JsonMultitypeSchemaWrapper(parent, scope, locator, jsonPointer,
vtype == ValueType.ARRAY ? type_value.asJsonArray() : null)
.read(this, object);
}

final AbstractJsonSchema schema;
switch(type) {
case OBJECT: schema = new JsonObjectSchemaImpl(parent, locator, jsonPointer); break;
case ARRAY: schema = new JsonArraySchemaImpl(parent, locator, jsonPointer); break;
case STRING: schema = new JsonStringSchemaImpl(parent, locator, jsonPointer); break;
case NUMBER: schema = new JsonNumberSchemaImpl(parent, locator, jsonPointer); break;
case INTEGER: schema = new JsonIntegerSchemaImpl(parent, locator, jsonPointer); break;
case BOOLEAN: schema = new JsonBooleanSchemaImpl(parent, locator, jsonPointer); break;
case NULL: schema = new JsonNullSchemaImpl(parent, locator, jsonPointer); break;
case OBJECT: schema = new JsonObjectSchemaImpl(parent, scope, locator, jsonPointer); break;
case ARRAY: schema = new JsonArraySchemaImpl(parent, scope, locator, jsonPointer); break;
case STRING: schema = new JsonStringSchemaImpl(parent, scope, locator, jsonPointer); break;
case NUMBER: schema = new JsonNumberSchemaImpl(parent, scope, locator, jsonPointer); break;
case INTEGER: schema = new JsonIntegerSchemaImpl(parent, scope, locator, jsonPointer); break;
case BOOLEAN: schema = new JsonBooleanSchemaImpl(parent, scope, locator, jsonPointer); break;
case NULL: schema = new JsonNullSchemaImpl(parent, scope, locator, jsonPointer); break;
default: return null;
}

Expand All @@ -180,11 +183,36 @@ public JsonSchemaVersion getJsonSchemaVersion(JsonSchemaLocator locator) {
} catch (IOException ex) {}

final Object version = properties.get(JsonSchemaParserConfig.JSON_SCHEMA_VERSION);
if (version instanceof JsonSchemaVersion) {
return (JsonSchemaVersion)version;
if (version instanceof JsonSchemaVersion v) {
return v;
}

return JsonSchemaVersion.SCHEMA_DRAFT_07; // default
}

private JsonSchemaLocator getScope(JsonSchemaLocator locator, JsonObject object)
throws JsonSchemaException {

JsonValue $id = object.get(JsonSchema.ID);
if ($id == null) {
$id = object.get("id"); // draft4
}

if ($id != null) {
if ($id.getValueType() != JsonValue.ValueType.STRING) {
throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
"id", $id.getValueType().name(), JsonValue.ValueType.STRING.name()));
} else {
final String id = ((JsonString)$id).getString();
try {
locator = locator.resolve(URI.create(id));
locator.setSchema(object);
} catch(IllegalArgumentException ex) {
throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_REFERENCE, id));
}
}
}

return locator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public interface PrimitiveSchema<T extends JsonSchema> extends JsonSchema {
public final static String THEN = "then";
public final static String ELSE = "else";

String getAnchor();
String getDynamicAnchor();
Boolean getRecursiveAnchor();

JsonAllOf getAllOf();
JsonAnyOf getAnyOf();
JsonOneOf getOneOf();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public abstract class AbstractJsonReferenceImpl extends AbstractJsonSchema<JsonO
protected JsonSchemaLocator ref_locator;
protected JsonSubschemaParser parser;

public AbstractJsonReferenceImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public AbstractJsonReferenceImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

protected void read(JsonSubschemaParser parser, JsonObject object, String tag)
Expand All @@ -72,21 +72,21 @@ protected void read(JsonSubschemaParser parser, JsonObject object, String tag)
final String fragment = ref.getFragment();
if (fragment == null) {
ref_pointer = "/";
ref_locator = getScope().resolve(ref);
ref_locator = scope.resolve(ref);
} else if ("#".equals(jref)) {
ref_pointer = "/";
ref_locator = getScope();
ref_locator = scope;
} else if (fragment.startsWith("/")) {
ref_pointer = fragment;
if (jref.startsWith("#")) {
ref_locator = getScope();
ref_locator = scope;
} else {
ref_locator = getScope().resolve(
ref_locator = scope.resolve(
new URI(ref.getScheme(), ref.getSchemeSpecificPart(), null));
}
} else {
ref_pointer = "/";
ref_locator = getScope().resolve(ref);
ref_locator = scope.resolve(ref);
}
} catch(JsonException | IllegalArgumentException | URISyntaxException ex) {
throw new JsonSchemaException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
public abstract class AbstractJsonSchema<T extends JsonValue>
extends AbstractJsonSchemaElement implements JsonSchema {

public AbstractJsonSchema(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public AbstractJsonSchema(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

public AbstractJsonSchema<T> read(JsonSubschemaParser parser, T value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,54 @@
import java.net.URI;

/**
* This is an root class that any JSON Schema element inherits from.
* It contains minimum properties to identify and locate the element in
* parsed JSON Schema tree.
*
* @author Dmitry Repchevsky
*/

public abstract class AbstractJsonSchemaElement implements JsonSchemaElement {

public final AbstractJsonSchemaElement parent;

public final JsonSchemaLocator scope;
public final JsonSchemaLocator locator;
private final String jsonPointer;

public AbstractJsonSchemaElement(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
public final String jsonPointer;

/**
* Constructor of the object.
* It only sets an essential properties to identify and locate the element in
* the JSON Schema.
*
* @param parent a parent element that encloses this one
* @param scope current element scope (may or may not be equal to the location)
* @param locator the locator that was used to load this document
* @param jsonPointer JSON Pointer to the parsed JSON Value that represents this element.
*/
public AbstractJsonSchemaElement(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {

this.parent = parent;

this.scope = scope;
this.locator = locator;
this.jsonPointer = jsonPointer.startsWith("//") ? jsonPointer.substring(1) : jsonPointer;
}

@Override
public final URI getId() {
return getScope().uri;
return scope.uri;
}

@Override
public String getJsonPointer() {
// when scope != locator (new scope) jsonPointer is 'root'
return getScope() == locator ? jsonPointer : "/";
return scope == locator ? jsonPointer : "/";
}

@Override
public AbstractJsonSchemaElement getParent() {
return parent;
}

public JsonSchemaLocator getScope() {
return locator;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public class BooleanJsonSchemaImpl extends AbstractJsonSchema<JsonValue>

private boolean evaluation;

public BooleanJsonSchemaImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public BooleanJsonSchemaImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
public class JsonAllOfImpl extends SchemaArrayImpl<JsonValue>
implements JsonAllOf<AbstractJsonSchema> {

public JsonAllOfImpl(AbstractJsonSchema parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public JsonAllOfImpl(AbstractJsonSchema parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
public class JsonAnyOfImpl<T extends JsonValue> extends SchemaArrayImpl<T>
implements JsonAnyOf<AbstractJsonSchema> {

public JsonAnyOfImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public JsonAnyOfImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import java.util.ArrayList;
import java.util.List;
import es.elixir.bsc.json.schema.impl.JsonSubschemaParser;
import static es.elixir.bsc.json.schema.model.JsonArraySchema.ADDITIONAL_ITEMS;
import es.elixir.bsc.json.schema.model.JsonSchemaElement;
import java.util.HashSet;
import java.util.Set;
Expand Down Expand Up @@ -70,9 +69,9 @@ public class JsonArraySchemaImpl extends PrimitiveSchemaImpl
private Long minContains;
private Long maxContains;

public JsonArraySchemaImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public JsonArraySchemaImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down Expand Up @@ -174,7 +173,7 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)

final JsonValue jcontains = object.get(CONTAINS);
if (jcontains != null) {
contains = parser.parse(getScope(), this, getJsonPointer() + "/" + CONTAINS, jcontains, null);
contains = parser.parse(scope, this, getJsonPointer() + "/" + CONTAINS, jcontains, null);
}

final JsonNumber jminContains = JsonSchemaUtil.check(object.getJsonNumber(MIN_CONTAINS), JsonValue.ValueType.NUMBER);
Expand All @@ -192,7 +191,7 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)
switch(jitems.getValueType()) {
case OBJECT:
case TRUE:
case FALSE: final AbstractJsonSchema schema = parser.parse(getScope(), this, getJsonPointer() + "/" + ITEMS, jitems, null);
case FALSE: final AbstractJsonSchema schema = parser.parse(scope, this, getJsonPointer() + "/" + ITEMS, jitems, null);
getItems().add(schema);
break;
case ARRAY: additionalItems = true;
Expand All @@ -201,7 +200,7 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)
switch(value.getValueType()) {
case OBJECT:
case TRUE:
case FALSE: final AbstractJsonSchema arr = parser.parse(getScope(), this, getJsonPointer() + "/" + ITEMS + "/" + i, value, null);
case FALSE: final AbstractJsonSchema arr = parser.parse(scope, this, getJsonPointer() + "/" + ITEMS + "/" + i, value, null);
getItems().add(arr);
break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
Expand All @@ -225,15 +224,15 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
ADDITIONAL_ITEMS, jadditionalItems.getValueType().name(), "either object or boolean"));
}
additionalItemsSchema = parser.parse(getScope(), this, getJsonPointer() + "/" + ADDITIONAL_ITEMS, jadditionalItems, null);
additionalItemsSchema = parser.parse(scope, this, getJsonPointer() + "/" + ADDITIONAL_ITEMS, jadditionalItems, null);
}
}

final JsonValue junevaluatedItems = object.get(UNEVALUATED_ITEMS);
if (junevaluatedItems != null) {
switch(junevaluatedItems.getValueType()) {
case OBJECT: unevaluatedItems = null;
unevaluatedItemsSchema = parser.parse(getScope(), this, getJsonPointer() + "/" + UNEVALUATED_ITEMS, junevaluatedItems, null);
unevaluatedItemsSchema = parser.parse(scope, this, getJsonPointer() + "/" + UNEVALUATED_ITEMS, junevaluatedItems, null);
break;
case TRUE: unevaluatedItems = true; break;
case FALSE: unevaluatedItems = false; break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
public class JsonBooleanSchemaImpl extends PrimitiveSchemaImpl
implements JsonBooleanSchema {

public JsonBooleanSchemaImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public JsonBooleanSchemaImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public class JsonConstImpl extends PrimitiveSchemaImpl implements JsonConst {

private JsonValue value;

public JsonConstImpl(AbstractJsonSchemaElement parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
public JsonConstImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@
public class JsonDependentPropertiesImpl extends AbstractJsonSchemaElement
implements JsonDependentProperties {

private final Map<String, StringArray> properties;
private final Map<String, StringArray> properties = new LinkedHashMap();

public JsonDependentPropertiesImpl(AbstractJsonSchema parent, JsonSchemaLocator locator,
String jsonPointer) {
super(parent, locator, jsonPointer);
properties = new LinkedHashMap();
public JsonDependentPropertiesImpl(AbstractJsonSchema parent,
JsonSchemaLocator scope, JsonSchemaLocator locator, String jsonPointer) {
super(parent, scope, locator, jsonPointer);
}

@Override
Expand Down
Loading

0 comments on commit e094457

Please sign in to comment.