diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 00000000..d9d19f5c
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ io.github.sebastian-toepfer.json-schema
+ json-schema
+ 0.1.0-SNAPSHOT
+
+
+ json-schema-api
+ Json Schema :: api
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+ org.hamcrest
+ hamcrest
+ test
+
+
+
+ jakarta.json
+ jakarta.json-api
+ provided
+
+
+
+ org.eclipse.parsson
+ parsson
+ test
+
+
+
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/ConstraintViolation.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/ConstraintViolation.java
similarity index 95%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/ConstraintViolation.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/ConstraintViolation.java
index ca12797f..06a3d018 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/ConstraintViolation.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/ConstraintViolation.java
@@ -21,6 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
public final class ConstraintViolation {}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/InstanceType.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/InstanceType.java
similarity index 97%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/InstanceType.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/InstanceType.java
index 31bd7b50..ffac968d 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/InstanceType.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/InstanceType.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
import jakarta.json.JsonNumber;
import jakarta.json.JsonValue;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchema.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchema.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchema.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchema.java
index 3c1a07ab..98ffbcb4 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchema.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchema.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
import jakarta.json.JsonValue;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchemas.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchemas.java
similarity index 93%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchemas.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchemas.java
index df60a3bf..68fecd04 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/JsonSchemas.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/JsonSchemas.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
-import io.github.sebastiantoepfer.jsonschema.core.spi.JsonSchemaFactory;
+import io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory;
import jakarta.json.Json;
import jakarta.json.JsonReader;
import jakarta.json.JsonValue;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Validator.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/Validator.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Validator.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/Validator.java
index acb54a1d..26c6305e 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Validator.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/Validator.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
import jakarta.json.Json;
import jakarta.json.JsonReader;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Vocabulary.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/Vocabulary.java
similarity index 91%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Vocabulary.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/Vocabulary.java
index abe04c48..62f22a24 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Vocabulary.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/Vocabulary.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core;
+package io.github.sebastiantoepfer.jsonschema;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.KeywordType;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
import java.net.URI;
import java.util.Optional;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Annotation.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Annotation.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Annotation.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Annotation.java
index 08efb16c..f7e2ae47 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Annotation.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Annotation.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import jakarta.json.JsonValue;
import java.util.Collection;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Applicator.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Applicator.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Applicator.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Applicator.java
index c72ef964..6fefab8c 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Applicator.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Applicator.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import jakarta.json.JsonValue;
import java.util.Collection;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Assertion.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Assertion.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Assertion.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Assertion.java
index 08f674fc..2def625a 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Assertion.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Assertion.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import jakarta.json.JsonValue;
import java.util.Collection;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotation.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotation.java
similarity index 97%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotation.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotation.java
index 53729a5f..52ba76c3 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotation.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotation.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import jakarta.json.JsonValue;
import java.util.Objects;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Identifier.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Identifier.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Identifier.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Identifier.java
index 16818b10..e947d35e 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Identifier.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Identifier.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import java.net.URI;
import java.util.Collection;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Keyword.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Keyword.java
similarity index 97%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Keyword.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Keyword.java
index 9b4b9b15..40e55913 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/Keyword.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/Keyword.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import java.util.Collection;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordType.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordType.java
similarity index 95%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordType.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordType.java
index 85f08a56..edb6a275 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordType.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordType.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import jakarta.json.JsonValue;
import java.util.Objects;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocation.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocation.java
similarity index 96%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocation.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocation.java
index fec1a07d..0f8956e8 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocation.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocation.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import java.util.Collection;
import java.util.Set;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/spi/JsonSchemaFactory.java b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/spi/JsonSchemaFactory.java
similarity index 91%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/spi/JsonSchemaFactory.java
rename to api/src/main/java/io/github/sebastiantoepfer/jsonschema/spi/JsonSchemaFactory.java
index b0f1180d..81a0d245 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/spi/JsonSchemaFactory.java
+++ b/api/src/main/java/io/github/sebastiantoepfer/jsonschema/spi/JsonSchemaFactory.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.spi;
+package io.github.sebastiantoepfer.jsonschema.spi;
-import io.github.sebastiantoepfer.jsonschema.core.JsonSchema;
+import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import jakarta.json.JsonValue;
public interface JsonSchemaFactory {
diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java
new file mode 100644
index 00000000..9ead3edd
--- /dev/null
+++ b/api/src/main/java/module-info.java
@@ -0,0 +1,31 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+module io.github.sebastiantoepfer.jsonschema {
+ exports io.github.sebastiantoepfer.jsonschema;
+ exports io.github.sebastiantoepfer.jsonschema.keyword;
+ exports io.github.sebastiantoepfer.jsonschema.spi;
+
+ requires jakarta.json;
+}
diff --git a/api/src/test/java/io/github/sebastiantoepfer/jsonschema/FakeJsonSchemaFactory.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/FakeJsonSchemaFactory.java
new file mode 100644
index 00000000..c294fd20
--- /dev/null
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/FakeJsonSchemaFactory.java
@@ -0,0 +1,45 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema;
+
+import io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory;
+import jakarta.json.JsonValue;
+
+public final class FakeJsonSchemaFactory implements JsonSchemaFactory {
+
+ @Override
+ public JsonSchema create(final JsonValue schema) {
+ return new JsonSchema() {
+ @Override
+ public Validator validator() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public JsonValue.ValueType getValueType() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ };
+ }
+}
diff --git a/api/src/test/java/io/github/sebastiantoepfer/jsonschema/InstanceTypeTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/InstanceTypeTest.java
new file mode 100644
index 00000000..7a45e2f4
--- /dev/null
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/InstanceTypeTest.java
@@ -0,0 +1,75 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import jakarta.json.Json;
+import jakarta.json.JsonValue;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class InstanceTypeTest {
+
+ @ParameterizedTest
+ @MethodSource("provideWithValidCombinations")
+ void should_be_true_if_instancetype_is_correct(final InstanceType instanceType, final JsonValue value) {
+ assertThat(instanceType.isInstance(value), is(true));
+ }
+
+ static Stream extends Arguments> provideWithValidCombinations() {
+ return Stream.of(
+ Arguments.of(InstanceType.NULL, JsonValue.NULL),
+ Arguments.of(InstanceType.BOOLEAN, JsonValue.FALSE),
+ Arguments.of(InstanceType.BOOLEAN, JsonValue.TRUE),
+ Arguments.of(InstanceType.OBJECT, JsonValue.EMPTY_JSON_OBJECT),
+ Arguments.of(InstanceType.ARRAY, JsonValue.EMPTY_JSON_ARRAY),
+ Arguments.of(InstanceType.NUMBER, Json.createValue(23L)),
+ Arguments.of(InstanceType.INTEGER, Json.createValue(23L)),
+ Arguments.of(InstanceType.INTEGER, Json.createValue(0.0))
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideWithInvalidCombinations")
+ void should_be_false_if_instancetype_is_correct(final InstanceType instanceType, final JsonValue value) {
+ assertThat(instanceType.isInstance(value), is(false));
+ }
+
+ static Stream extends Arguments> provideWithInvalidCombinations() {
+ return Stream.of(
+ Arguments.of(InstanceType.NULL, JsonValue.TRUE),
+ Arguments.of(InstanceType.BOOLEAN, JsonValue.EMPTY_JSON_OBJECT),
+ Arguments.of(InstanceType.BOOLEAN, JsonValue.EMPTY_JSON_ARRAY),
+ Arguments.of(InstanceType.OBJECT, JsonValue.EMPTY_JSON_ARRAY),
+ Arguments.of(InstanceType.ARRAY, JsonValue.TRUE),
+ Arguments.of(InstanceType.NUMBER, Json.createValue("string")),
+ Arguments.of(InstanceType.INTEGER, Json.createValue(23.2)),
+ Arguments.of(InstanceType.INTEGER, Json.createValue("test"))
+ );
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/TypeTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/JsonSchemasTest.java
similarity index 77%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/TypeTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/JsonSchemasTest.java
index 500b1734..49d64128 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/TypeTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/JsonSchemasTest.java
@@ -21,23 +21,19 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
-import jakarta.json.Json;
import org.junit.jupiter.api.Test;
-class TypeTest {
+class JsonSchemasTest {
@Test
- void should_know_his_name() {
- assertThat(new Type(Json.createValue("string")).hasName("type"), is(true));
- }
-
- @Test
- void should_know_other_names() {
- assertThat(new Type(Json.createValue("string")).hasName("id"), is(false));
+ void should_return_a_schema() {
+ assertThat(JsonSchemas.load("{}"), is(not(nullValue())));
}
}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AnnotationTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AnnotationTest.java
similarity index 97%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AnnotationTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AnnotationTest.java
index e0967efc..a1998142 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AnnotationTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AnnotationTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ApplicatorTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ApplicatorTest.java
similarity index 97%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ApplicatorTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ApplicatorTest.java
index 0d7b786e..85a2aabd 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ApplicatorTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ApplicatorTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AssertionTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AssertionTest.java
similarity index 97%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AssertionTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AssertionTest.java
index 1a354692..63322eb5 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/AssertionTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/AssertionTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotationTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotationTest.java
similarity index 96%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotationTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotationTest.java
index 753d1796..775cbb66 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/DefaultAnnotationTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/DefaultAnnotationTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/IdentifierTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/IdentifierTest.java
similarity index 94%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/IdentifierTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/IdentifierTest.java
index cd492ea8..36085e82 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/IdentifierTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/IdentifierTest.java
@@ -21,12 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.Keyword.KeywordCategory;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword.KeywordCategory;
import java.net.URI;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordTypeTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordTypeTest.java
similarity index 96%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordTypeTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordTypeTest.java
index 6a3d95df..028e7290 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/KeywordTypeTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/KeywordTypeTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocationTest.java b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocationTest.java
similarity index 97%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocationTest.java
rename to api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocationTest.java
index a85dbc02..22cca4aa 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/keyword/ReservedLocationTest.java
+++ b/api/src/test/java/io/github/sebastiantoepfer/jsonschema/keyword/ReservedLocationTest.java
@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.keyword;
+package io.github.sebastiantoepfer.jsonschema.keyword;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
diff --git a/api/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory b/api/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory
new file mode 100644
index 00000000..78479819
--- /dev/null
+++ b/api/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory
@@ -0,0 +1 @@
+io.github.sebastiantoepfer.jsonschema.FakeJsonSchemaFactory
diff --git a/core/pom.xml b/core/pom.xml
index 86e23439..2300dc22 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -14,14 +14,19 @@
- org.junit.jupiter
- junit-jupiter-api
- test
+ ${project.groupId}
+ json-schema-api
+ ${project.version}
${project.groupId}
- json-schema-testsuite-junit-platform-engine
+ json-schema-vocabulary-spi
${project.version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
test
@@ -29,6 +34,11 @@
junit-jupiter-engine
test
+
+ org.junit.jupiter
+ junit-jupiter-params
+ test
+
org.hamcrest
@@ -46,6 +56,12 @@
jakarta.json-api
provided
+
+
+ org.eclipse.parsson
+ parsson
+ test
+
@@ -104,6 +120,24 @@
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ run-jsonschema-testsuite
+
+ test
+
+
+
+ **/JsonTestSuiteIT.java
+
+
+
+
+
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchema.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchema.java
similarity index 93%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchema.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchema.java
index 2f92fa8c..09a7ea53 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchema.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchema.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.JsonSchema;
+import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchema.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchema.java
similarity index 61%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchema.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchema.java
index 74790bab..ebe4f145 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchema.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchema.java
@@ -21,22 +21,28 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.AllOfConstraint;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.Constraint;
-import io.github.sebastiantoepfer.jsonschema.core.impl.keyword.Keywords;
+import io.github.sebastiantoepfer.jsonschema.Validator;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.AllOfConstraint;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.VocabularyKeywordType;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinition;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinitions;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
+import java.util.Collection;
-public final class DefaultJsonSchema extends AbstractJsonValueSchema {
+final class DefaultJsonSchema extends AbstractJsonValueSchema {
+
+ private final Keywords keywords;
public DefaultJsonSchema(final JsonObject value) {
super(value);
+ keywords = new Keywords(vocabulary());
}
@Override
@@ -44,11 +50,21 @@ public Validator validator() {
return asJsonObject()
.entrySet()
.stream()
- .map(Keywords::createKeywordFor)
+ .map(keywords::createKeywordFor)
.filter(Constraint.class::isInstance)
.map(k -> (Constraint) k)
.collect(
collectingAndThen(toList(), constraints -> new DefaultValidator(new AllOfConstraint<>(constraints)))
);
}
+
+ private Collection vocabulary() {
+ return new KeywordSearch(new VocabularyKeywordType())
+ .searchForKeywordIn(asJsonObject())
+ .filter(VocabularyDefinitions.class::isInstance)
+ .map(VocabularyDefinitions.class::cast)
+ .stream()
+ .flatMap(VocabularyDefinitions::definitions)
+ .toList();
+ }
}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchemaFactory.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactory.java
similarity index 89%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchemaFactory.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactory.java
index 5b8ea7d5..49bf94c9 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultJsonSchemaFactory.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactory.java
@@ -21,10 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.JsonSchema;
-import io.github.sebastiantoepfer.jsonschema.core.spi.JsonSchemaFactory;
+import io.github.sebastiantoepfer.jsonschema.JsonSchema;
+import io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory;
import jakarta.json.JsonValue;
public final class DefaultJsonSchemaFactory implements JsonSchemaFactory {
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultValidator.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultValidator.java
similarity index 85%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultValidator.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultValidator.java
index 61890a42..62d35a2e 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/DefaultValidator.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/DefaultValidator.java
@@ -21,11 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.Validator;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.Constraint;
import jakarta.json.JsonValue;
import java.util.Collection;
import java.util.Objects;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/EmptyJsonSchema.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchema.java
similarity index 87%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/EmptyJsonSchema.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchema.java
index 8db7d282..17a2e73b 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/EmptyJsonSchema.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchema.java
@@ -21,10 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.NoConstraint;
+import io.github.sebastiantoepfer.jsonschema.Validator;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.NoConstraint;
import jakarta.json.JsonValue;
final class EmptyJsonSchema extends AbstractJsonValueSchema {
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/FalseJsonSchema.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchema.java
similarity index 87%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/FalseJsonSchema.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchema.java
index 48b4eaa8..eee71fe6 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/FalseJsonSchema.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchema.java
@@ -21,10 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.UnfulfillableConstraint;
+import io.github.sebastiantoepfer.jsonschema.Validator;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.UnfulfillableConstraint;
import jakarta.json.JsonValue;
final class FalseJsonSchema extends AbstractJsonValueSchema {
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/KeywordSearch.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/KeywordSearch.java
new file mode 100644
index 00000000..5c5c9325
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/KeywordSearch.java
@@ -0,0 +1,43 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonObject;
+import java.util.Objects;
+import java.util.Optional;
+
+final class KeywordSearch {
+
+ private final KeywordType keywordType;
+
+ public KeywordSearch(final KeywordType keywordType) {
+ this.keywordType = Objects.requireNonNull(keywordType);
+ }
+
+ public Optional searchForKeywordIn(final JsonObject schema) {
+ return Optional.ofNullable(schema.get(keywordType.name())).map(keywordType::createKeyword);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Keywords.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Keywords.java
new file mode 100644
index 00000000..eb8a6d2d
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/Keywords.java
@@ -0,0 +1,92 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static java.util.function.Predicate.not;
+import static java.util.stream.Collectors.toMap;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.basic.BasicVocabulary;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.CoreVocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinition;
+import jakarta.json.JsonValue;
+import java.net.URI;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
+
+final class Keywords {
+
+ private static final Map MANDANTORY_VOCABS;
+
+ static {
+ MANDANTORY_VOCABS =
+ List
+ .of(new BasicVocabulary(), new CoreVocabulary())
+ .stream()
+ .collect(toMap(Vocabulary::id, Function.identity()));
+ }
+
+ private final Collection vocabularies;
+
+ public Keywords(final Collection vocabDefs) {
+ if (
+ vocabDefs
+ .stream()
+ .filter(vocabDef -> MANDANTORY_VOCABS.containsKey(vocabDef.id()))
+ .anyMatch(not(VocabularyDefinition::required))
+ ) {
+ throw new IllegalArgumentException("can not be created without core vocabulary is requiered!");
+ }
+ vocabularies =
+ Stream
+ .concat(
+ MANDANTORY_VOCABS.values().stream(),
+ vocabDefs.stream().map(VocabularyDefinition::findVocabulary).flatMap(Optional::stream)
+ )
+ .collect(
+ Collector.of(
+ ArrayDeque::new,
+ ArrayDeque::addFirst,
+ (first, last) -> null //pitest otherwise see mutants here :(
+ )
+ );
+ }
+
+ public Keyword createKeywordFor(final Map.Entry property) {
+ return vocabularies
+ .stream()
+ .map(vocab -> vocab.findKeywordTypeByName(property.getKey()))
+ .flatMap(Optional::stream)
+ .findFirst()
+ .map(keywordType -> keywordType.createKeyword(property.getValue()))
+ .orElseThrow();
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/TrueJsonSchema.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchema.java
similarity index 87%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/TrueJsonSchema.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchema.java
index aae77a7e..8cc4b777 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/TrueJsonSchema.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchema.java
@@ -21,10 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.NoConstraint;
+import io.github.sebastiantoepfer.jsonschema.Validator;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.NoConstraint;
import jakarta.json.JsonValue;
final class TrueJsonSchema extends AbstractJsonValueSchema {
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AllOfConstraint.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AllOfConstraint.java
similarity index 93%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AllOfConstraint.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AllOfConstraint.java
index 9f661b0c..657b557a 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AllOfConstraint.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AllOfConstraint.java
@@ -21,12 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.constraint;
+package io.github.sebastiantoepfer.jsonschema.core.constraint;
import static java.util.Arrays.asList;
import static java.util.function.Predicate.not;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
import java.util.Collection;
import java.util.List;
import java.util.Set;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AnyConstraint.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AnyConstraint.java
similarity index 94%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AnyConstraint.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AnyConstraint.java
index cdf54e83..e4454126 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/AnyConstraint.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/AnyConstraint.java
@@ -21,12 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.constraint;
+package io.github.sebastiantoepfer.jsonschema.core.constraint;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toSet;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
import java.util.Collection;
import java.util.List;
import java.util.Set;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/Constraint.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/Constraint.java
similarity index 90%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/Constraint.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/Constraint.java
index 291d6b25..18bc877f 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/Constraint.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/Constraint.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.constraint;
+package io.github.sebastiantoepfer.jsonschema.core.constraint;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
import java.util.Collection;
public interface Constraint {
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/NoConstraint.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/NoConstraint.java
similarity index 90%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/NoConstraint.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/NoConstraint.java
index f3aebcf1..1c0ffc7d 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/NoConstraint.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/NoConstraint.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.constraint;
+package io.github.sebastiantoepfer.jsonschema.core.constraint;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
import java.util.Collection;
import java.util.Set;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/UnfulfillableConstraint.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/UnfulfillableConstraint.java
similarity index 90%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/UnfulfillableConstraint.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/UnfulfillableConstraint.java
index f351d498..78f27e04 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/constraint/UnfulfillableConstraint.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/constraint/UnfulfillableConstraint.java
@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.constraint;
+package io.github.sebastiantoepfer.jsonschema.core.constraint;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
import java.util.Collection;
import java.util.Set;
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Type.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Type.java
deleted file mode 100644
index 2fa13a7d..00000000
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Type.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The MIT License
- *
- * Copyright 2023 sebastian.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
-
-import static java.util.stream.Collectors.collectingAndThen;
-import static java.util.stream.Collectors.toList;
-
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
-import io.github.sebastiantoepfer.jsonschema.core.InstanceType;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.AnyConstraint;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.Constraint;
-import jakarta.json.JsonArray;
-import jakarta.json.JsonString;
-import jakarta.json.JsonValue;
-import java.util.Collection;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * see: https://json-schema.org/understanding-json-schema/reference/type.html
- */
-final class Type implements ConstraintAssertion, Constraint {
-
- private final JsonValue definition;
-
- public Type(final JsonValue definition) {
- this.definition = Objects.requireNonNull(definition);
- }
-
- @Override
- public boolean hasName(final String name) {
- return Objects.equals("type", name);
- }
-
- @Override
- public Collection violationsBy(final JsonValue value) {
- return new JsonMappedTypeConstaint(definition).violationsBy(value);
- }
-
- private static final class JsonMappedTypeConstaint implements Constraint {
-
- private final JsonValue definition;
-
- public JsonMappedTypeConstaint(final JsonValue definition) {
- this.definition = Objects.requireNonNull(definition);
- }
-
- @Override
- public Collection violationsBy(final JsonValue value) {
- final Constraint typeContraint =
- switch (definition.getValueType()) {
- case STRING -> new JsonStringTypeConstraint((JsonString) definition);
- default -> new JsonArrayTypeConstraint(definition.asJsonArray());
- };
- return typeContraint.violationsBy(value);
- }
- }
-
- private static final class JsonArrayTypeConstraint implements Constraint {
-
- private final JsonArray types;
-
- public JsonArrayTypeConstraint(final JsonArray types) {
- this.types = Objects.requireNonNull(types);
- }
-
- @Override
- public Collection violationsBy(final JsonValue value) {
- return types
- .stream()
- .map(JsonMappedTypeConstaint::new)
- .collect(collectingAndThen(toList(), AnyConstraint::new))
- .violationsBy(value);
- }
- }
-
- private static final class JsonStringTypeConstraint implements Constraint {
-
- private final String type;
-
- public JsonStringTypeConstraint(final JsonString type) {
- this.type = Objects.requireNonNull(type).getString().toUpperCase(Locale.US);
- }
-
- @Override
- public Collection violationsBy(final JsonValue value) {
- final InstanceType instanceType = InstanceType.valueOf(type);
- final Collection result;
- if (instanceType.isInstance(value)) {
- result = Set.of();
- } else {
- result = Set.of(new ConstraintViolation());
- }
- return result;
- }
- }
-}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertion.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertion.java
similarity index 82%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertion.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertion.java
index 14e75640..8c01a472 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertion.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertion.java
@@ -21,16 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema.core.vocab;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.Constraint;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.Assertion;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.keyword.Assertion;
import jakarta.json.JsonValue;
/**
* only simplify pitest :)
*/
-interface ConstraintAssertion extends Assertion, Constraint {
+public interface ConstraintAssertion extends Assertion, Constraint {
@Override
default boolean isValidFor(JsonValue instance) {
return violationsBy(instance).isEmpty();
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabulary.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabulary.java
similarity index 52%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabulary.java
rename to core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabulary.java
index d5fd1c35..decce0b8 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabulary.java
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabulary.java
@@ -21,17 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema.core.vocab.basic;
-import io.github.sebastiantoepfer.jsonschema.core.Vocabulary;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.DefaultAnnotation;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.Keyword;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.KeywordType;
-import jakarta.json.JsonValue;
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
import java.net.URI;
import java.util.Optional;
-final class BasicVocabulary implements Vocabulary {
+public final class BasicVocabulary implements Vocabulary {
@Override
public URI id() {
@@ -40,31 +37,11 @@ public URI id() {
@Override
public Optional findKeywordTypeByName(final String name) {
- KeywordType keywordType =
+ return Optional.of(
switch (name) {
- case "type" -> new KeywordType() {
- @Override
- public String name() {
- return "type";
- }
-
- @Override
- public Keyword createKeyword(final JsonValue value) {
- return new Type(value);
- }
- };
- default -> new KeywordType() {
- @Override
- public String name() {
- return name;
- }
-
- @Override
- public Keyword createKeyword(final JsonValue value) {
- return new DefaultAnnotation(name(), value);
- }
- };
- };
- return Optional.of(keywordType);
+ case "type" -> new TypeKeywordType();
+ default -> new UnknowKeywordType(name);
+ }
+ );
}
}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeKeywordType.java
new file mode 100644
index 00000000..c3ef73f4
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeKeywordType.java
@@ -0,0 +1,135 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.basic;
+
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
+
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.InstanceType;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.AnyConstraint;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.ConstraintAssertion;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonString;
+import jakarta.json.JsonValue;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * see: https://json-schema.org/understanding-json-schema/reference/type.html
+ */
+final class TypeKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "type";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new TypeKeyword(value);
+ }
+
+ private final class TypeKeyword implements ConstraintAssertion, Constraint {
+
+ private final JsonValue definition;
+
+ public TypeKeyword(final JsonValue definition) {
+ this.definition = Objects.requireNonNull(definition);
+ }
+
+ @Override
+ public boolean hasName(final String name) {
+ return Objects.equals(name(), name);
+ }
+
+ @Override
+ public Collection violationsBy(final JsonValue value) {
+ return new JsonMappedTypeConstaint(definition).violationsBy(value);
+ }
+
+ private static final class JsonMappedTypeConstaint implements Constraint {
+
+ private final JsonValue definition;
+
+ public JsonMappedTypeConstaint(final JsonValue definition) {
+ this.definition = Objects.requireNonNull(definition);
+ }
+
+ @Override
+ public Collection violationsBy(final JsonValue value) {
+ final Constraint typeContraint =
+ switch (definition.getValueType()) {
+ case STRING -> new JsonStringTypeConstraint((JsonString) definition);
+ default -> new JsonArrayTypeConstraint(definition.asJsonArray());
+ };
+ return typeContraint.violationsBy(value);
+ }
+ }
+
+ private static final class JsonArrayTypeConstraint implements Constraint {
+
+ private final JsonArray types;
+
+ public JsonArrayTypeConstraint(final JsonArray types) {
+ this.types = Objects.requireNonNull(types);
+ }
+
+ @Override
+ public Collection violationsBy(final JsonValue value) {
+ return types
+ .stream()
+ .map(JsonMappedTypeConstaint::new)
+ .collect(collectingAndThen(toList(), AnyConstraint::new))
+ .violationsBy(value);
+ }
+ }
+
+ private static final class JsonStringTypeConstraint implements Constraint {
+
+ private final String type;
+
+ public JsonStringTypeConstraint(final JsonString type) {
+ this.type = Objects.requireNonNull(type).getString().toUpperCase(Locale.US);
+ }
+
+ @Override
+ public Collection violationsBy(final JsonValue value) {
+ final InstanceType instanceType = InstanceType.valueOf(type);
+ final Collection result;
+ if (instanceType.isInstance(value)) {
+ result = Set.of();
+ } else {
+ result = Set.of(new ConstraintViolation());
+ }
+ return result;
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/UnknowKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/UnknowKeywordType.java
new file mode 100644
index 00000000..d3d86476
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/UnknowKeywordType.java
@@ -0,0 +1,49 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.basic;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.DefaultAnnotation;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+import java.util.Objects;
+
+final class UnknowKeywordType implements KeywordType {
+
+ private final String name;
+
+ public UnknowKeywordType(final String name) {
+ this.name = Objects.requireNonNull(name);
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new DefaultAnnotation(name(), value);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CommentKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CommentKeywordType.java
new file mode 100644
index 00000000..985f2922
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CommentKeywordType.java
@@ -0,0 +1,46 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.DefaultAnnotation;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-comments-with-comment
+ */
+final class CommentKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$comment";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new DefaultAnnotation(name(), value);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabulary.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabulary.java
new file mode 100644
index 00000000..33b7477e
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabulary.java
@@ -0,0 +1,58 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu
+ */
+public final class CoreVocabulary implements Vocabulary {
+
+ private Collection supportedKeywords = List.of(
+ new SchemaKeywordType(),
+ new VocabularyKeywordType(),
+ new IdKeywordType(),
+ new RefKeywordType(),
+ new DynamicRefKeywordType(),
+ new DefsKeywordType(),
+ new CommentKeywordType()
+ );
+
+ @Override
+ public URI id() {
+ //we need a way to find out which draft we are using!
+ return URI.create("https://json-schema.org/draft/2020-12/vocab/core");
+ }
+
+ @Override
+ public Optional findKeywordTypeByName(final String name) {
+ return supportedKeywords.stream().filter(keywordType -> keywordType.hasName(name)).findFirst();
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DefsKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DefsKeywordType.java
new file mode 100644
index 00000000..ed4e0d33
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DefsKeywordType.java
@@ -0,0 +1,46 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.DefaultAnnotation;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-schema-re-use-with-defs
+ */
+final class DefsKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$defs";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new DefaultAnnotation(name(), value);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordType.java
new file mode 100644
index 00000000..390c58b4
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordType.java
@@ -0,0 +1,58 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.Applicator;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+import java.util.Objects;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-dynamic-references-with-dyn
+ */
+final class DynamicRefKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$dynamicRef";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new Applicator() {
+ @Override
+ public boolean applyTo(final JsonValue instance) {
+ //something is wrong here
+ return true;
+ }
+
+ @Override
+ public boolean hasName(final String name) {
+ return Objects.equals(name(), name);
+ }
+ };
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/IdKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/IdKeywordType.java
new file mode 100644
index 00000000..6bf3fa21
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/IdKeywordType.java
@@ -0,0 +1,46 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.DefaultAnnotation;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-id-keyword
+ */
+final class IdKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$id";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new DefaultAnnotation(name(), value);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabulary.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabulary.java
new file mode 100644
index 00000000..82edca2e
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabulary.java
@@ -0,0 +1,50 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies;
+import java.net.URI;
+import java.util.Objects;
+import java.util.Optional;
+
+public final class LazyCoreVocabulary implements LazyVocabularies {
+
+ private final Vocabulary vocab;
+
+ public LazyCoreVocabulary() {
+ this.vocab = new CoreVocabulary();
+ }
+
+ @Override
+ public Optional loadVocabularyWithId(final URI id) {
+ final Optional result;
+ if (Objects.equals(id, vocab.id())) {
+ result = Optional.of(vocab);
+ } else {
+ result = Optional.empty();
+ }
+ return result;
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordType.java
new file mode 100644
index 00000000..b59ba3a6
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordType.java
@@ -0,0 +1,57 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.Applicator;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+import java.util.Objects;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-direct-references-with-ref
+ */
+final class RefKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$ref";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new Applicator() {
+ @Override
+ public boolean applyTo(final JsonValue instance) {
+ return true; //something is wrong here
+ }
+
+ @Override
+ public boolean hasName(final String name) {
+ return Objects.equals(name(), name);
+ }
+ };
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/SchemaKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/SchemaKeywordType.java
new file mode 100644
index 00000000..926ec37c
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/SchemaKeywordType.java
@@ -0,0 +1,46 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.keyword.DefaultAnnotation;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
+
+/**
+ *
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-schema-keyword
+ */
+final class SchemaKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$schema";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ return new DefaultAnnotation(name(), value);
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordType.java b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordType.java
new file mode 100644
index 00000000..2ff582e8
--- /dev/null
+++ b/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordType.java
@@ -0,0 +1,94 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import io.github.sebastiantoepfer.jsonschema.InstanceType;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinition;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinitions;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * see: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-vocabulary-keyword
+ */
+public final class VocabularyKeywordType implements KeywordType {
+
+ @Override
+ public String name() {
+ return "$vocabulary";
+ }
+
+ @Override
+ public Keyword createKeyword(final JsonValue value) {
+ final Keyword result;
+ if (InstanceType.OBJECT.isInstance(value)) {
+ result = new VocabularyKeyword(value);
+ } else {
+ throw new IllegalArgumentException(
+ "must be an object! " +
+ "read https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-vocabulary-keyword" +
+ "for more infromations"
+ );
+ }
+ return result;
+ }
+
+ public final class VocabularyKeyword implements Keyword, VocabularyDefinitions {
+
+ private final JsonObject vocabularies;
+
+ VocabularyKeyword(final JsonValue vocabularies) {
+ this(vocabularies.asJsonObject());
+ }
+
+ VocabularyKeyword(final JsonObject vocabularies) {
+ this.vocabularies = Objects.requireNonNull(vocabularies);
+ }
+
+ @Override
+ public Collection categories() {
+ return List.of();
+ }
+
+ @Override
+ public boolean hasName(final String name) {
+ return Objects.equals(name(), name);
+ }
+
+ @Override
+ public Stream definitions() {
+ return vocabularies
+ .entrySet()
+ .stream()
+ .map(entry -> new VocabularyDefinition(URI.create(entry.getKey()), entry.getValue() == JsonValue.TRUE));
+ }
+ }
+}
diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java
index 99eafb82..1bcda2e5 100644
--- a/core/src/main/java/module-info.java
+++ b/core/src/main/java/module-info.java
@@ -22,8 +22,13 @@
* THE SOFTWARE.
*/
module io.github.sebastiantoepfer.jsonschema.core {
- exports io.github.sebastiantoepfer.jsonschema.core;
- exports io.github.sebastiantoepfer.jsonschema.core.keyword;
-
+ requires io.github.sebastiantoepfer.jsonschema;
+ requires io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
requires jakarta.json;
+
+ provides io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory
+ with io.github.sebastiantoepfer.jsonschema.core.DefaultJsonSchemaFactory;
+
+ provides io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies
+ with io.github.sebastiantoepfer.jsonschema.core.vocab.core.LazyCoreVocabulary;
}
diff --git a/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.core.spi.JsonSchemaFactory b/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.core.spi.JsonSchemaFactory
deleted file mode 100644
index b2dd1495..00000000
--- a/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.core.spi.JsonSchemaFactory
+++ /dev/null
@@ -1 +0,0 @@
-io.github.sebastiantoepfer.jsonschema.core.impl.spi.DefaultJsonSchemaFactory
diff --git a/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory b/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory
new file mode 100644
index 00000000..f38f8f8b
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.spi.JsonSchemaFactory
@@ -0,0 +1 @@
+io.github.sebastiantoepfer.jsonschema.core.DefaultJsonSchemaFactory
diff --git a/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies b/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies
new file mode 100644
index 00000000..68cddf8a
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies
@@ -0,0 +1 @@
+io.github.sebastiantoepfer.jsonschema.core.vocab.core.LazyCoreVocabulary
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchemaTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchemaTest.java
similarity index 88%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchemaTest.java
rename to core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchemaTest.java
index 7b31aff2..b660641b 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/spi/AbstractJsonValueSchemaTest.java
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/AbstractJsonValueSchemaTest.java
@@ -21,14 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.spi;
+package io.github.sebastiantoepfer.jsonschema.core;
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.core.impl.spi.AbstractJsonValueSchema;
+import io.github.sebastiantoepfer.jsonschema.Validator;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactoryTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactoryTest.java
new file mode 100644
index 00000000..bab69f66
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaFactoryTest.java
@@ -0,0 +1,61 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+
+import jakarta.json.Json;
+import jakarta.json.JsonValue;
+import org.junit.jupiter.api.Test;
+
+class DefaultJsonSchemaFactoryTest {
+
+ @Test
+ void should_return_truejsonschema_for_true() {
+ assertThat(new DefaultJsonSchemaFactory().create(JsonValue.TRUE), is(instanceOf(TrueJsonSchema.class)));
+ }
+
+ @Test
+ void should_return_truejsonschema_for_false() {
+ assertThat(new DefaultJsonSchemaFactory().create(JsonValue.FALSE), is(instanceOf(FalseJsonSchema.class)));
+ }
+
+ @Test
+ void should_return_emptyjsonschema_for_emptyobject() {
+ assertThat(
+ new DefaultJsonSchemaFactory().create(JsonValue.EMPTY_JSON_OBJECT),
+ is(instanceOf(EmptyJsonSchema.class))
+ );
+ }
+
+ @Test
+ void should_return_defaultjsonschema_for_everything_else() {
+ assertThat(
+ new DefaultJsonSchemaFactory().create(Json.createObjectBuilder().add("type", "string").build()),
+ is(instanceOf(DefaultJsonSchema.class))
+ );
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaTest.java
new file mode 100644
index 00000000..e0e3ac5b
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/DefaultJsonSchemaTest.java
@@ -0,0 +1,65 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class DefaultJsonSchemaTest {
+
+ private final DefaultJsonSchema schema = new DefaultJsonSchema(
+ Json.createObjectBuilder().add("type", "string").build()
+ );
+
+ @Test
+ void should_be_valid_for_string() {
+ assertThat(schema.validator().validate(Json.createValue("test")), is(empty()));
+ }
+
+ @Test
+ void should_be_invalid_for_object() {
+ assertThat(schema.validator().validate(JsonValue.EMPTY_JSON_OBJECT), is(not(empty())));
+ }
+
+ @Test
+ void should_not_be_loadable_without_mandantory_core_vocabulary() {
+ final JsonObject invalidSchema = Json
+ .createObjectBuilder()
+ .add(
+ "$vocabulary",
+ Json.createObjectBuilder().add("https://json-schema.org/draft/2020-12/vocab/core", false)
+ )
+ .build();
+
+ Assertions.assertThrows(Exception.class, () -> new DefaultJsonSchema(invalidSchema));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchemaTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchemaTest.java
new file mode 100644
index 00000000..657e981b
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/EmptyJsonSchemaTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+
+import jakarta.json.JsonValue;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+class EmptyJsonSchemaTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(JsonValuesArguments.class)
+ void should_be_valid_for_everything(final JsonValue value) {
+ assertThat(new EmptyJsonSchema().validator().validate(value), is(empty()));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchemaTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchemaTest.java
new file mode 100644
index 00000000..9819fcf6
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/FalseJsonSchemaTest.java
@@ -0,0 +1,42 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+import jakarta.json.JsonValue;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+class FalseJsonSchemaTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(JsonValuesArguments.class)
+ void should_be_invalid_for_everything(final JsonValue value) {
+ assertThat(new FalseJsonSchema().validator().validate(value), is(not(empty())));
+ }
+}
diff --git a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Keywords.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/JsonValuesArguments.java
similarity index 64%
rename from core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Keywords.java
rename to core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/JsonValuesArguments.java
index 2a81121e..13c5a4a2 100644
--- a/core/src/main/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/Keywords.java
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/JsonValuesArguments.java
@@ -21,25 +21,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema.core;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.Keyword;
import jakarta.json.JsonValue;
-import java.util.Map;
-import java.util.Optional;
import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
-public final class Keywords {
+public class JsonValuesArguments implements ArgumentsProvider {
- public static Keyword createKeywordFor(final Map.Entry property) {
- return Stream
- .of(new BasicVocabulary())
- .map(vocab -> vocab.findKeywordTypeByName(property.getKey()))
- .flatMap(Optional::stream)
- .findFirst()
- .map(keywordType -> keywordType.createKeyword(property.getValue()))
- .orElseThrow();
+ @Override
+ public Stream extends Arguments> provideArguments(final ExtensionContext context) throws Exception {
+ return Stream.of(
+ Arguments.of(JsonValue.EMPTY_JSON_ARRAY),
+ Arguments.of(JsonValue.EMPTY_JSON_OBJECT),
+ Arguments.of(JsonValue.FALSE),
+ Arguments.of(JsonValue.TRUE),
+ Arguments.of(JsonValue.NULL)
+ );
}
-
- private Keywords() {}
}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/KeywordsTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/KeywordsTest.java
new file mode 100644
index 00000000..1945fda6
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/KeywordsTest.java
@@ -0,0 +1,65 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import io.github.sebastiantoepfer.jsonschema.core.vocab.basic.BasicVocabulary;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.CoreVocabulary;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinition;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class KeywordsTest {
+
+ @Test
+ void should_not_be_createbale_without_mandantory_core_vocabulary() {
+ final Collection vocabDefs = List.of(
+ new VocabularyDefinition(new CoreVocabulary().id(), false)
+ );
+ assertThrows(IllegalArgumentException.class, () -> new Keywords(vocabDefs));
+ }
+
+ @Test
+ void should_not_be_createbale_without_mandantory_base_vocabulary() {
+ final Collection vocabDefs = List.of(
+ new VocabularyDefinition(new BasicVocabulary().id(), false)
+ );
+ assertThrows(IllegalArgumentException.class, () -> new Keywords(vocabDefs));
+ }
+
+ @Test
+ void should_be_createbale_with_optional_vocabularies() {
+ assertThat(
+ new Keywords(List.of(new VocabularyDefinition(URI.create("http://optinal"), false))),
+ is(not(nullValue()))
+ );
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchemaTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchemaTest.java
new file mode 100644
index 00000000..36f5ff5b
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/TrueJsonSchemaTest.java
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+
+import jakarta.json.JsonValue;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+class TrueJsonSchemaTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(JsonValuesArguments.class)
+ void should_be_valid_for_everything(final JsonValue value) {
+ assertThat(new TrueJsonSchema().validator().validate(value), is(empty()));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonSchemaSchemaTestValidatorAdapterLoader.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteIT.java
similarity index 56%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonSchemaSchemaTestValidatorAdapterLoader.java
rename to core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteIT.java
index 866ec232..a7f77238 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonSchemaSchemaTestValidatorAdapterLoader.java
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteIT.java
@@ -23,29 +23,16 @@
*/
package io.github.sebastiantoepfer.jsonschema.core.testsuite;
-import io.github.sebastiantoepfer.jsonschema.core.JsonSchemas;
-import io.github.sebastiantoepfer.jsonschema.core.Validator;
-import io.github.sebastiantoepfer.jsonschema.testsuite.junit.SchemaTestValidatorLoader;
-import java.util.Objects;
+import static org.junit.jupiter.api.Assertions.assertTrue;
-public final class JsonSchemaSchemaTestValidatorAdapterLoader implements SchemaTestValidatorLoader {
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
- @Override
- public SchemaTestValidator loadSchemaTestValidator(final String schema) {
- return new SchemaTestValidatorAdapter(JsonSchemas.load(schema).validator());
- }
-
- private static class SchemaTestValidatorAdapter implements SchemaTestValidator {
-
- private final Validator validator;
-
- public SchemaTestValidatorAdapter(final Validator validator) {
- this.validator = Objects.requireNonNull(validator);
- }
+class JsonTestSuiteIT {
- @Override
- public boolean validate(final String data) {
- return validator.validate(data).isEmpty();
- }
+ @ParameterizedTest(name = "{0}")
+ @ArgumentsSource(JsonTestSuiteTestCaseProvider.class)
+ void runJsonTestSuite(final JsonTestSuiteTestCase testcase) {
+ assertTrue(testcase.isValid());
}
}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCase.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCase.java
new file mode 100644
index 00000000..42358e35
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCase.java
@@ -0,0 +1,28 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.testsuite;
+
+interface JsonTestSuiteTestCase {
+ boolean isValid();
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCaseProvider.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCaseProvider.java
new file mode 100644
index 00000000..0656f74c
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/JsonTestSuiteTestCaseProvider.java
@@ -0,0 +1,124 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.testsuite;
+
+import io.github.sebastiantoepfer.jsonschema.JsonSchemas;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
+import jakarta.json.stream.JsonParser;
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+class JsonTestSuiteTestCaseProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(final ExtensionContext context) throws Exception {
+ return new Resources()
+ .all()
+ .filter(resource -> resource.hasExtension("json"))
+ .map(JsonSchemaTestSuites::new)
+ .flatMap(JsonSchemaTestSuites::allTestCases)
+ .map(Arguments::of);
+ }
+
+ private static class JsonSchemaTestSuites {
+
+ private final Resource jsonResource;
+
+ public JsonSchemaTestSuites(final Resource jsonResource) {
+ this.jsonResource = Objects.requireNonNull(jsonResource);
+ }
+
+ Stream allTestCases() {
+ final Stream result;
+ final JsonParser parser = Json.createParser(jsonResource.content());
+ if (parser.next() == JsonParser.Event.START_ARRAY) {
+ result =
+ parser
+ .getArrayStream()
+ .onClose(() -> parser.close())
+ .map(JsonValue::asJsonObject)
+ .map(JsonSchemaTestSuite::new)
+ .flatMap(JsonSchemaTestSuite::allTestCases);
+ } else {
+ parser.close();
+ result = Stream.empty();
+ }
+ return result;
+ }
+
+ private class JsonSchemaTestSuite {
+
+ private final JsonObject testsuite;
+
+ public JsonSchemaTestSuite(final JsonObject testsuite) {
+ this.testsuite = Objects.requireNonNull(testsuite);
+ }
+
+ Stream allTestCases() {
+ return testsuite
+ .getJsonArray("tests")
+ .stream()
+ .map(test -> new JsonSchemaTest(testsuite.get("schema"), test.asJsonObject()));
+ }
+
+ private class JsonSchemaTest implements JsonTestSuiteTestCase {
+
+ private final JsonValue schema;
+ private final JsonObject test;
+
+ public JsonSchemaTest(final JsonValue schema, final JsonObject test) {
+ this.schema = schema;
+ this.test = test;
+ }
+
+ @Override
+ public boolean isValid() {
+ return (
+ JsonSchemas.load(schema).validator().validate(test.get("data")).isEmpty() ==
+ test.getBoolean("valid")
+ );
+ }
+
+ @Override
+ public String toString() {
+ return (
+ "JsonSchemaTest{" +
+ "schema=" +
+ schema +
+ ", test=" +
+ test +
+ " in " +
+ JsonSchemaTestSuites.this.jsonResource.name() +
+ '}'
+ );
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resource.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resource.java
new file mode 100644
index 00000000..cfa43487
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resource.java
@@ -0,0 +1,68 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.testsuite;
+
+import java.io.InputStream;
+import java.util.Objects;
+
+final record Resource(String name) {
+ boolean hasName(final String name) {
+ return Objects.equals(this.name, name);
+ }
+
+ boolean hasExtension(final String extension) {
+ return name.endsWith(".".concat(extension));
+ }
+
+ InputStream content() {
+ return Resource.class.getClassLoader().getResourceAsStream(name);
+ }
+
+ @Override
+ public String toString() {
+ return "Resource{" + "name=" + name + '}';
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Resource other = (Resource) obj;
+ return (this.name == null) ? (other.name == null) : this.name.equals(other.name);
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resources.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resources.java
new file mode 100644
index 00000000..26f785d8
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/testsuite/Resources.java
@@ -0,0 +1,119 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.testsuite;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+final class Resources {
+
+ private final String baseDir;
+
+ public Resources() {
+ this(".");
+ }
+
+ public Resources(final String baseDir) {
+ this.baseDir = baseDir;
+ }
+
+ Stream all() {
+ try {
+ return StreamSupport
+ .stream(
+ Spliterators.spliteratorUnknownSize(
+ Resource.class.getClassLoader().getResources(baseDir).asIterator(),
+ Spliterator.ORDERED
+ ),
+ false
+ )
+ .map(url -> {
+ try {
+ return url.toURI();
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(e);
+ }
+ })
+ .filter(uri -> "file".equals(uri.getScheme()))
+ .map(Paths::get)
+ .map(PathResources::new)
+ .flatMap(PathResources::toResources);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static class PathResources {
+
+ private static final Pattern PATH_SEPARATOR = Pattern.compile(File.pathSeparator);
+ private final Path path;
+
+ public PathResources(final Path path) {
+ this.path = Objects.requireNonNull(path);
+ }
+
+ Stream toResources() {
+ final Stream result;
+ try {
+ if (path.toFile().isFile()) {
+ result =
+ Stream.of(
+ new Resource(
+ path
+ .toFile()
+ .getAbsolutePath()
+ .substring(
+ PATH_SEPARATOR
+ .splitAsStream(System.getProperty("java.class.path"))
+ .map(Path::of)
+ .filter(path::startsWith)
+ .map(Path::toFile)
+ .map(File::getAbsolutePath)
+ .map(String::length)
+ .map(i -> i + 1)
+ .findAny()
+ .orElse(0)
+ )
+ )
+ );
+ } else {
+ result = Files.list(path).map(PathResources::new).flatMap(PathResources::toResources);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return result;
+ }
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertionTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertionTest.java
similarity index 89%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertionTest.java
rename to core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertionTest.java
index 15abc7af..6561f6cd 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/ConstraintAssertionTest.java
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/ConstraintAssertionTest.java
@@ -21,13 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema.core.vocab;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import io.github.sebastiantoepfer.jsonschema.core.ConstraintViolation;
-import io.github.sebastiantoepfer.jsonschema.core.impl.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.ConstraintViolation;
+import io.github.sebastiantoepfer.jsonschema.core.constraint.Constraint;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.ConstraintAssertion;
import jakarta.json.JsonValue;
import java.util.Collection;
import java.util.Objects;
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabularyTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabularyTest.java
similarity index 79%
rename from core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabularyTest.java
rename to core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabularyTest.java
index 63eb5e96..75962d00 100644
--- a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/impl/keyword/BasicVocabularyTest.java
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/BasicVocabularyTest.java
@@ -21,13 +21,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package io.github.sebastiantoepfer.jsonschema.core.impl.keyword;
+package io.github.sebastiantoepfer.jsonschema.core.vocab.basic;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import com.github.npathai.hamcrestopt.OptionalMatchers;
-import io.github.sebastiantoepfer.jsonschema.core.keyword.KeywordType;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.basic.BasicVocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import jakarta.json.JsonValue;
import java.net.URI;
import org.junit.jupiter.api.Test;
@@ -52,8 +54,11 @@ void should_return_the_type_keywordtype() {
@Test
void should_return_the_custom_annotation_for_unknow_keyword() {
assertThat(
- new BasicVocabulary().findKeywordTypeByName("unknow").map(KeywordType::name),
- OptionalMatchers.isPresentAndIs("unknow")
+ new BasicVocabulary()
+ .findKeywordTypeByName("unknow")
+ .map(keywordType -> keywordType.createKeyword(JsonValue.FALSE))
+ .map(keyword -> keyword.hasName("unknow")),
+ OptionalMatchers.isPresentAndIs(true)
);
}
}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeTest.java
new file mode 100644
index 00000000..88fcd282
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/basic/TypeTest.java
@@ -0,0 +1,70 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.basic;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import io.github.sebastiantoepfer.jsonschema.core.vocab.basic.TypeKeywordType;
+import io.github.sebastiantoepfer.jsonschema.keyword.Assertion;
+import jakarta.json.Json;
+import jakarta.json.JsonValue;
+import org.junit.jupiter.api.Test;
+
+class TypeTest {
+
+ @Test
+ void should_know_his_name() {
+ assertThat(new TypeKeywordType().createKeyword(Json.createValue("string")).hasName("type"), is(true));
+ }
+
+ @Test
+ void should_know_other_names() {
+ assertThat(new TypeKeywordType().createKeyword(Json.createValue("string")).hasName("id"), is(false));
+ }
+
+ @Test
+ void should_use_stringvalue_to_validate_type() {
+ final Assertion typeAssertion = new TypeKeywordType().createKeyword(Json.createValue("string")).asAssertion();
+
+ assertThat(typeAssertion.isValidFor(Json.createValue("value")), is(true));
+ assertThat(typeAssertion.isValidFor(JsonValue.EMPTY_JSON_OBJECT), is(false));
+ assertThat(typeAssertion.isValidFor(Json.createValue(1L)), is(false));
+ assertThat(typeAssertion.isValidFor(JsonValue.EMPTY_JSON_ARRAY), is(false));
+ }
+
+ @Test
+ void should_use_arrayvalue_to_validate_type() {
+ final Assertion typeAssertion = new TypeKeywordType()
+ .createKeyword(
+ Json.createArrayBuilder().add(Json.createValue("string")).add(Json.createValue("object")).build()
+ )
+ .asAssertion();
+
+ assertThat(typeAssertion.isValidFor(Json.createValue("value")), is(true));
+ assertThat(typeAssertion.isValidFor(JsonValue.EMPTY_JSON_OBJECT), is(true));
+ assertThat(typeAssertion.isValidFor(Json.createValue(1L)), is(false));
+ assertThat(typeAssertion.isValidFor(JsonValue.EMPTY_JSON_ARRAY), is(false));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabularyTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabularyTest.java
new file mode 100644
index 00000000..392e842e
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/CoreVocabularyTest.java
@@ -0,0 +1,54 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import com.github.npathai.hamcrestopt.OptionalMatchers;
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.CoreVocabulary;
+import jakarta.json.JsonValue;
+import java.net.URI;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class CoreVocabularyTest {
+
+ void should_return_the_uri_of_the_current_core_vocabulary() {
+ assertThat(new CoreVocabulary().id(), is(URI.create("https://json-schema.org/draft/2020-12/vocab/core")));
+ }
+
+ @ParameterizedTest(name = "should know keyword {0}")
+ @ValueSource(strings = { "$schema", "$vocabulary", "$id", "$ref", "$dynamicRef", "$defs", "$comment" })
+ void should_return_keywords_for_name(final String name) {
+ //keyword creation for easier pitesting :) -> i know it is bad
+ assertThat(
+ new CoreVocabulary()
+ .findKeywordTypeByName(name)
+ .map(keywordType -> keywordType.createKeyword(JsonValue.EMPTY_JSON_OBJECT))
+ .map(keyword -> keyword.hasName(name)),
+ OptionalMatchers.isPresentAndIs(true)
+ );
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordTypeTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordTypeTest.java
new file mode 100644
index 00000000..4a6dfb94
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/DynamicRefKeywordTypeTest.java
@@ -0,0 +1,45 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.DynamicRefKeywordType;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import jakarta.json.JsonValue;
+import org.junit.jupiter.api.Test;
+
+class DynamicRefKeywordTypeTest {
+
+ @Test
+ void notFinischedYet() {
+ final Keyword keyword = new DynamicRefKeywordType().createKeyword(JsonValue.FALSE);
+
+ assertThat(keyword.hasName("$dynamicRef"), is(true));
+ assertThat(keyword.hasName("$id"), is(false));
+
+ assertThat(keyword.asApplicator().applyTo(JsonValue.TRUE), is(true));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabularyTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabularyTest.java
new file mode 100644
index 00000000..5f1aed0e
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/LazyCoreVocabularyTest.java
@@ -0,0 +1,50 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import static com.github.npathai.hamcrestopt.OptionalMatchers.isEmpty;
+import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresentAndIs;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import java.net.URI;
+import org.junit.jupiter.api.Test;
+
+class LazyCoreVocabularyTest {
+
+ @Test
+ void should_return_empty_for_non_core_id() {
+ assertThat(new LazyCoreVocabulary().loadVocabularyWithId(URI.create("")), isEmpty());
+ }
+
+ @Test
+ void should_return_core_vocabulary_for_core_id() {
+ assertThat(
+ new LazyCoreVocabulary()
+ .loadVocabularyWithId(URI.create("https://json-schema.org/draft/2020-12/vocab/core"))
+ .map(Vocabulary::id),
+ isPresentAndIs(URI.create("https://json-schema.org/draft/2020-12/vocab/core"))
+ );
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordTypeTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordTypeTest.java
new file mode 100644
index 00000000..345da416
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/RefKeywordTypeTest.java
@@ -0,0 +1,45 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.RefKeywordType;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import jakarta.json.JsonValue;
+import org.junit.jupiter.api.Test;
+
+class RefKeywordTypeTest {
+
+ @Test
+ void notFinischedYet() {
+ final Keyword keyword = new RefKeywordType().createKeyword(JsonValue.FALSE);
+
+ assertThat(keyword.hasName("$ref"), is(true));
+ assertThat(keyword.hasName("$id"), is(false));
+
+ assertThat(keyword.asApplicator().applyTo(JsonValue.TRUE), is(true));
+ }
+}
diff --git a/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordTypeTest.java b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordTypeTest.java
new file mode 100644
index 00000000..45923f04
--- /dev/null
+++ b/core/src/test/java/io/github/sebastiantoepfer/jsonschema/core/vocab/core/VocabularyKeywordTypeTest.java
@@ -0,0 +1,74 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.core.vocab.core;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.is;
+
+import io.github.sebastiantoepfer.jsonschema.core.vocab.core.VocabularyKeywordType;
+import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinition;
+import io.github.sebastiantoepfer.jsonschema.vocabulary.spi.VocabularyDefinitions;
+import jakarta.json.Json;
+import jakarta.json.JsonValue;
+import java.net.URI;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class VocabularyKeywordTypeTest {
+
+ @Test
+ void should_not_create_keyword_for_non_jsonobject() {
+ final VocabularyKeywordType keywordType = new VocabularyKeywordType();
+ Assertions.assertThrows(IllegalArgumentException.class, () -> keywordType.createKeyword(JsonValue.FALSE));
+ }
+
+ @Test
+ void should_created_keyword_should_know_his_name() {
+ final Keyword vocabulary = new VocabularyKeywordType().createKeyword(JsonValue.EMPTY_JSON_OBJECT);
+
+ assertThat(vocabulary.hasName("$vocabulary"), is(true));
+ assertThat(vocabulary.hasName("$id"), is(false));
+ }
+
+ @Test
+ void should_create_definitions() {
+ assertThat(
+ ((VocabularyDefinitions) new VocabularyKeywordType()
+ .createKeyword(
+ Json
+ .createObjectBuilder()
+ .add("http://json-schema.org/test", true)
+ .add("http://openapi.org/test", false)
+ .build()
+ )).definitions()
+ .toList(),
+ containsInAnyOrder(
+ new VocabularyDefinition(URI.create("http://json-schema.org/test"), true),
+ new VocabularyDefinition(URI.create("http://openapi.org/test"), false)
+ )
+ );
+ }
+}
diff --git a/core/src/test/java/module-info.java b/core/src/test/java/module-info.java
index 1d06fa1a..b7ce75fd 100644
--- a/core/src/test/java/module-info.java
+++ b/core/src/test/java/module-info.java
@@ -22,10 +22,12 @@
* THE SOFTWARE.
*/
open module io.github.sebastiantoepfer.jsonschema.core {
+ requires io.github.sebastiantoepfer.jsonschema;
+ requires io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
requires jakarta.json;
- requires io.github.sebastiantoepfer.jsonschema.testsuite.junit;
requires org.junit.jupiter.api;
+ requires org.junit.jupiter.params;
requires org.junit.jupiter.engine;
requires org.hamcrest;
}
diff --git a/core/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.testsuite.junit.SchemaTestValidatorLoader b/core/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.testsuite.junit.SchemaTestValidatorLoader
deleted file mode 100644
index eb2d5163..00000000
--- a/core/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.testsuite.junit.SchemaTestValidatorLoader
+++ /dev/null
@@ -1 +0,0 @@
-io.github.sebastiantoepfer.jsonschema.core.testsuite.JsonSchemaSchemaTestValidatorAdapterLoader
diff --git a/pom.xml b/pom.xml
index a73a1e9c..d16ec52d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,7 +52,9 @@
testsuite-junit-platform-engine
- core
+ api
+ vocabulary-spi
+ core
@@ -244,6 +246,9 @@
toString
hashCode
+
+ **IT
+
diff --git a/vocabulary-spi/pom.xml b/vocabulary-spi/pom.xml
new file mode 100644
index 00000000..e3227436
--- /dev/null
+++ b/vocabulary-spi/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+ 4.0.0
+
+
+ io.github.sebastian-toepfer.json-schema
+ json-schema
+ 0.1.0-SNAPSHOT
+
+
+ json-schema-vocabulary-spi
+ Json Schema :: vocabulary :: spi
+
+
+
+ ${project.groupId}
+ json-schema-api
+ ${project.version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+ org.hamcrest
+ hamcrest
+ test
+
+
+ com.github.npathai
+ hamcrest-optional
+ test
+
+
+
diff --git a/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabularies.java b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabularies.java
new file mode 100644
index 00000000..05d7fd67
--- /dev/null
+++ b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabularies.java
@@ -0,0 +1,36 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import java.net.URI;
+import java.util.Optional;
+
+public interface LazyVocabularies {
+ default boolean knowsId(URI id) {
+ return loadVocabularyWithId(id).isPresent();
+ }
+
+ Optional loadVocabularyWithId(URI id);
+}
diff --git a/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinition.java b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinition.java
new file mode 100644
index 00000000..0d4ab838
--- /dev/null
+++ b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinition.java
@@ -0,0 +1,45 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import java.net.URI;
+import java.util.Optional;
+import java.util.ServiceLoader;
+
+public record VocabularyDefinition(URI id, boolean required) {
+ public Optional findVocabulary() {
+ final Optional result = ServiceLoader
+ .load(LazyVocabularies.class)
+ .stream()
+ .map(ServiceLoader.Provider::get)
+ .map(loader -> loader.loadVocabularyWithId(id))
+ .flatMap(Optional::stream)
+ .findFirst();
+ if (result.isEmpty() && required) {
+ throw new IllegalStateException("can not find required vocabulary: " + id);
+ }
+ return result;
+ }
+}
diff --git a/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitions.java b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitions.java
new file mode 100644
index 00000000..fe9dd85f
--- /dev/null
+++ b/vocabulary-spi/src/main/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitions.java
@@ -0,0 +1,30 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import java.util.stream.Stream;
+
+public interface VocabularyDefinitions {
+ Stream definitions();
+}
diff --git a/vocabulary-spi/src/main/java/module-info.java b/vocabulary-spi/src/main/java/module-info.java
new file mode 100644
index 00000000..68e99b3f
--- /dev/null
+++ b/vocabulary-spi/src/main/java/module-info.java
@@ -0,0 +1,29 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+module io.github.sebastiantoepfer.jsonschema.vocabulary.spi {
+ exports io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+ requires io.github.sebastiantoepfer.jsonschema;
+}
diff --git a/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabulariesTest.java b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabulariesTest.java
new file mode 100644
index 00000000..fb7f777b
--- /dev/null
+++ b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/LazyVocabulariesTest.java
@@ -0,0 +1,67 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import java.net.URI;
+import java.util.Objects;
+import java.util.Optional;
+import org.junit.jupiter.api.Test;
+
+class LazyVocabulariesTest implements LazyVocabularies {
+
+ @Test
+ void should_know_which_vocabularies_are_supported() {
+ assertThat(knowsId(URI.create("http://github.com/sebastian-toepfer/json-schema/basic")), is(true));
+ assertThat(knowsId(URI.create("http://invalid")), is(false));
+ }
+
+ @Override
+ public Optional loadVocabularyWithId(final URI id) {
+ final Optional result;
+ if (Objects.equals(URI.create("http://github.com/sebastian-toepfer/json-schema/basic"), id)) {
+ result =
+ Optional.of(
+ new Vocabulary() {
+ @Override
+ public URI id() {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public Optional findKeywordTypeByName(String name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+ );
+ } else {
+ result = Optional.empty();
+ }
+ return result;
+ }
+}
diff --git a/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/TestLazyVocabularies.java b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/TestLazyVocabularies.java
new file mode 100644
index 00000000..e9efbd88
--- /dev/null
+++ b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/TestLazyVocabularies.java
@@ -0,0 +1,53 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import io.github.sebastiantoepfer.jsonschema.keyword.KeywordType;
+import java.net.URI;
+import java.util.Optional;
+
+public final class TestLazyVocabularies implements LazyVocabularies {
+
+ @Override
+ public Optional loadVocabularyWithId(final URI id) {
+ if (id.equals(URI.create("https://json-schema.org/draft/2020-12/vocab/core"))) {
+ return Optional.of(
+ new Vocabulary() {
+ @Override
+ public URI id() {
+ return id;
+ }
+
+ @Override
+ public Optional findKeywordTypeByName(String name) {
+ return Optional.empty();
+ }
+ }
+ );
+ } else {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitionTest.java b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitionTest.java
new file mode 100644
index 00000000..dd582c88
--- /dev/null
+++ b/vocabulary-spi/src/test/java/io/github/sebastiantoepfer/jsonschema/vocabulary/spi/VocabularyDefinitionTest.java
@@ -0,0 +1,60 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2023 sebastian.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package io.github.sebastiantoepfer.jsonschema.vocabulary.spi;
+
+import static com.github.npathai.hamcrestopt.OptionalMatchers.isEmpty;
+import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresentAndIs;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import io.github.sebastiantoepfer.jsonschema.Vocabulary;
+import java.net.URI;
+import org.junit.jupiter.api.Test;
+
+class VocabularyDefinitionTest {
+
+ @Test
+ void should_throw_illegal_state_if_a_required_vocabulary_can_not_be_loaded() {
+ final VocabularyDefinition vocabDef = new VocabularyDefinition(URI.create("https://invalid"), true);
+ assertThrows(IllegalStateException.class, () -> vocabDef.findVocabulary());
+ }
+
+ @Test
+ void should_find_mandatory_core_vocabulary() {
+ assertThat(
+ new VocabularyDefinition(URI.create("https://json-schema.org/draft/2020-12/vocab/core"), true)
+ .findVocabulary()
+ .map(Vocabulary::id),
+ isPresentAndIs(URI.create("https://json-schema.org/draft/2020-12/vocab/core"))
+ );
+ }
+
+ @Test
+ void should_retrun_empty_for_optional_vocabulary_which_can_not_be_loaded() {
+ assertThat(
+ new VocabularyDefinition(URI.create("https://invalid"), false).findVocabulary().map(Vocabulary::id),
+ isEmpty()
+ );
+ }
+}
diff --git a/vocabulary-spi/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies b/vocabulary-spi/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies
new file mode 100644
index 00000000..7f7bf604
--- /dev/null
+++ b/vocabulary-spi/src/test/resources/META-INF/services/io.github.sebastiantoepfer.jsonschema.vocabulary.spi.LazyVocabularies
@@ -0,0 +1 @@
+io.github.sebastiantoepfer.jsonschema.vocabulary.spi.TestLazyVocabularies