Skip to content

Commit

Permalink
add support for 'prefixItems' (2020-12)
Browse files Browse the repository at this point in the history
  • Loading branch information
redmitry committed Aug 30, 2024
1 parent 7a44798 commit 7222006
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 42 deletions.
23 changes: 19 additions & 4 deletions src/main/java/es/elixir/bsc/json/schema/model/JsonArraySchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
public interface JsonArraySchema extends JsonSchema {

public final static String ITEMS = "items";
public final static String PREFIX_ITEMS = "prefixItems";
public final static String UNIQUE_ITEMS = "uniqueItems";
public final static String ADDITIONAL_ITEMS = "additionalItems";
public final static String UNEVALUATED_ITEMS = "unevaluatedItems";
Expand All @@ -54,19 +55,33 @@ public interface JsonArraySchema extends JsonSchema {
void setMaxItems(Long maxItems);

/**
* returns a list that contain one or more schemas.
*
* In 2020-12 returns immutable list with just one schema.
* In 2019-09 and before the list may contain more schemas.
*
* In a case where there is only one schema in the list it is
* either {...} or [{...}].Setting 'additionalItems' to <b>NULL</b>
* means there is a single schema and not an array with only one schema defined.
*
* @param <T>
* either {...} or [{...}].
*
* @param <T> any implementation specific class that implements JsonSchema
*
* @return list of schemas
*/
<T extends JsonSchema> List<T> getItems();

/**
* Returns 2020-12 'prefixItems'
*
* @param <T> any implementation specific class that implements JsonSchema
* @return
*/
<T extends JsonSchema> List<T> getPrefixItems();

Boolean isUniqueItems();

/**
* Returns 'additionalSchema' or 'items' in the 2020-09
*
* @param <T>
*
* @return 'additionalSchema' JsonSchema, <b>NULL</b> if FALSE (or not set),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@
public class JsonArraySchemaImpl extends PrimitiveSchemaImpl
implements JsonArraySchema {

private List<AbstractJsonSchema> items;
private final List<AbstractJsonSchema> items;

// the items are actually a 'prefixItems'
private boolean prefixItems;

private Boolean additionalItems;
private Boolean uniqueItems;
private AbstractJsonSchema additionalItemsSchema;
Expand All @@ -74,6 +78,8 @@ public class JsonArraySchemaImpl extends PrimitiveSchemaImpl
public JsonArraySchemaImpl(AbstractJsonSchemaElement parent,
JsonSchemaLocator locator, String jsonPointer) {
super(parent, locator, jsonPointer);

items = new ArrayList();
}

@Override
Expand All @@ -93,11 +99,15 @@ public Stream<AbstractJsonSchemaElement> getChildren() {

@Override
public List<AbstractJsonSchema> getItems() {
if (items == null) {
items = new ArrayList<>();
}

return items;
// in 2020-12 'items' is a schema
return prefixItems ? additionalItemsSchema != null ? List.of(additionalItemsSchema) : null : items;
}

@Override
public List<AbstractJsonSchema> getPrefixItems() {
// 2019-09 'items' == 2020-12 'prefixItems'
// 2019-09 'additionalItemsSchema' == 2020-12 'items'
return prefixItems ? items : null;
}

@Override
Expand Down Expand Up @@ -155,7 +165,7 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)
throws JsonSchemaException {

super.read(parser, object);

final JsonNumber min = JsonSchemaUtil.check(object.getJsonNumber(MIN_ITEMS), JsonValue.ValueType.NUMBER);
if (min != null) {
minItems = min.longValue();
Expand Down Expand Up @@ -192,47 +202,59 @@ public JsonArraySchemaImpl read(JsonSubschemaParser parser, JsonObject object)
}

JsonValue jitems = object.get(ITEMS);
if (jitems != null) {
JsonValue jadditionalItems = object.get(ADDITIONAL_ITEMS);

JsonArray jprefixitems = JsonSchemaUtil.check(object.get(PREFIX_ITEMS), JsonValue.ValueType.ARRAY);
if (jprefixitems != null) {
// in 2020-12 when 'prefixItems' is defined 'items' are 'additionalItems'
prefixItems = true;
jadditionalItems = jitems;
} else if (jitems != null) {
switch(jitems.getValueType()) {
case OBJECT:
case TRUE:
case FALSE: final AbstractJsonSchema schema = parser.parse(locator, this, getJsonPointer() + "/" + ITEMS, jitems, null);
getItems().add(schema);
items.add(schema);
break;
case ARRAY: additionalItems = true;
for (int i = 0, n = jitems.asJsonArray().size(); i < n; i++) {
final JsonValue value = jitems.asJsonArray().get(i);
switch(value.getValueType()) {
case OBJECT:
case TRUE:
case FALSE: final AbstractJsonSchema arr = parser.parse(locator, this, getJsonPointer() + "/" + ITEMS + "/" + i, value, null);
getItems().add(arr);
break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
ITEMS + "/" + i, value.getValueType().name(), "either an object or boolean"));
}
}
case ARRAY: jprefixitems = jitems.asJsonArray();
break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
ITEMS, jitems.getValueType().name(), "either an object, boolean or an array"));

}
}

if (additionalItems != null) {
final JsonValue jadditionalItems = object.get(ADDITIONAL_ITEMS);
if (jadditionalItems != null) {
switch(jadditionalItems.getValueType()) {
case OBJECT: additionalItems = null; break;
case FALSE: additionalItems = false;
case TRUE: break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
ADDITIONAL_ITEMS, jadditionalItems.getValueType().name(), "either object or boolean"));

if (jprefixitems != null) {
additionalItems = true;

final String propertyName = prefixItems ? PREFIX_ITEMS : ITEMS;

for (int i = 0, n = jprefixitems.size(); i < n; i++) {
final JsonValue value = jprefixitems.get(i);
switch(value.getValueType()) {
case OBJECT:
case TRUE:
case FALSE: final AbstractJsonSchema arr = parser.parse(locator, this, getJsonPointer() + "/" + propertyName + "/" + i, value, null);
items.add(arr);
break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
propertyName + "/" + i, value.getValueType().name(), "either an object or boolean"));
}
additionalItemsSchema = parser.parse(locator, this, getJsonPointer() + "/" + ADDITIONAL_ITEMS, jadditionalItems, null);
}
}

if (additionalItems != null && jadditionalItems != null) {
final String propertyName = jadditionalItems == jitems ? ITEMS : ADDITIONAL_ITEMS;

switch(jadditionalItems.getValueType()) {
case OBJECT: break;
case FALSE: additionalItems = false;
case TRUE: break;
default: throw new JsonSchemaException(new ParsingError(ParsingMessage.INVALID_ATTRIBUTE_TYPE,
propertyName, jadditionalItems.getValueType().name(), "either object or boolean"));
}
additionalItemsSchema = parser.parse(locator, this, getJsonPointer() + "/" + propertyName, jadditionalItems, null);
}

final JsonValue junevaluatedItems = object.get(UNEVALUATED_ITEMS);
if (junevaluatedItems != null) {
switch(junevaluatedItems.getValueType()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public void test_draft201909() {
test(JSON_DRAFT201909_TEST_FILE);
}

// @Test
// public void test_draft202012() {
// test(JSON_DRAFT202012_TEST_FILE);
// }
@Test
public void test_draft202012() {
test(JSON_DRAFT202012_TEST_FILE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* *****************************************************************************
* Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
* authors, or their employers as appropriate.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*****************************************************************************
*/

package es.elixir.bsc.json.schema.org.tests;

import org.junit.Test;

/**
* @author Dmitry Repchevsky
*/

public class JsonSchemaPrefixItemsTest extends JsonSchemaOrgTest {

private final static String JSON_DRAFT202012_TEST_FILE = "json-schema-org/tests/draft2020-12/prefixItems.json";

@Test
public void test_draft202012() {
test(JSON_DRAFT202012_TEST_FILE);
}
}

0 comments on commit 7222006

Please sign in to comment.