Skip to content

Commit

Permalink
refactor TypeKeywordType
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-toepfer committed Dec 3, 2023
1 parent bef87a4 commit 06b3127
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -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.codition;

import jakarta.json.JsonValue;
import java.util.Collection;
import java.util.List;

public class AnyOfCondition implements Condition<JsonValue> {

private final Collection<Condition<JsonValue>> conditions;

public AnyOfCondition(final Collection<Condition<JsonValue>> conditions) {
this.conditions = List.copyOf(conditions);
}

@Override
public boolean isFulfilledBy(final JsonValue value) {
return conditions.stream().anyMatch(c -> c.isFulfilledBy(value));
}
}
Original file line number Diff line number Diff line change
@@ -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.codition;

import io.github.sebastiantoepfer.jsonschema.InstanceType;
import jakarta.json.JsonValue;

public final class OfTypeCondition implements Condition<JsonValue> {

private final InstanceType type;

public OfTypeCondition(final InstanceType type) {
this.type = type;
}

@Override
public boolean isFulfilledBy(final JsonValue value) {
return type.isInstance(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,18 @@
*/
package io.github.sebastiantoepfer.jsonschema.core.vocab.validation;

import static jakarta.json.JsonValue.ValueType.STRING;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;

import io.github.sebastiantoepfer.jsonschema.InstanceType;
import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import io.github.sebastiantoepfer.jsonschema.core.codition.AnyOfCondition;
import io.github.sebastiantoepfer.jsonschema.core.codition.Condition;
import io.github.sebastiantoepfer.jsonschema.core.codition.OfTypeCondition;
import io.github.sebastiantoepfer.jsonschema.keyword.Assertion;
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.Locale;
Expand All @@ -47,14 +52,32 @@ public String name() {

@Override
public Keyword createKeyword(final JsonSchema schema) {
return new TypeKeyword(schema.asJsonObject().get(name()));
final JsonValue typeDefinition = schema.asJsonObject().get(name());
final Condition<JsonValue> typeContraint =
switch (typeDefinition.getValueType()) {
case STRING -> new OfTypeCondition(
InstanceType.valueOf(((JsonString) typeDefinition).getString().toUpperCase(Locale.US))
);
case ARRAY -> typeDefinition
.asJsonArray()
.stream()
.map(JsonString.class::cast)
.map(JsonString::getString)
.map(String::toUpperCase)
.map(InstanceType::valueOf)
.map(OfTypeCondition::new)
.collect(collectingAndThen(toList(), AnyOfCondition::new));
default -> throw new IllegalArgumentException();
};

return new TypeKeyword(typeContraint);
}

private final class TypeKeyword implements Assertion {

private final JsonValue definition;
private final Condition<JsonValue> definition;

public TypeKeyword(final JsonValue definition) {
public TypeKeyword(final Condition<JsonValue> definition) {
this.definition = Objects.requireNonNull(definition);
}

Expand All @@ -65,54 +88,7 @@ public boolean hasName(final String name) {

@Override
public boolean isValidFor(final JsonValue instance) {
return new JsonMappedTypeConstaint(definition).isFulfilledBy(instance);
}

private static final class JsonMappedTypeConstaint implements Condition<JsonValue> {

private final JsonValue definition;

public JsonMappedTypeConstaint(final JsonValue definition) {
this.definition = Objects.requireNonNull(definition);
}

@Override
public boolean isFulfilledBy(final JsonValue value) {
final Condition<JsonValue> typeContraint =
switch (definition.getValueType()) {
case STRING -> new JsonStringTypeConstraint((JsonString) definition);
default -> new JsonArrayTypeConstraint(definition.asJsonArray());
};
return typeContraint.isFulfilledBy(value);
}
}

private static final class JsonArrayTypeConstraint implements Condition<JsonValue> {

private final JsonArray types;

public JsonArrayTypeConstraint(final JsonArray types) {
this.types = Objects.requireNonNull(types);
}

@Override
public boolean isFulfilledBy(final JsonValue value) {
return types.stream().map(JsonMappedTypeConstaint::new).anyMatch(c -> c.isFulfilledBy(value));
}
}

private static final class JsonStringTypeConstraint implements Condition<JsonValue> {

private final String type;

public JsonStringTypeConstraint(final JsonString type) {
this.type = Objects.requireNonNull(type).getString().toUpperCase(Locale.US);
}

@Override
public boolean isFulfilledBy(final JsonValue value) {
return InstanceType.valueOf(type).isInstance(value);
}
return definition.isFulfilledBy(instance);
}
}
}

0 comments on commit 06b3127

Please sign in to comment.