Skip to content

Commit

Permalink
Merge pull request #160 from sebastian-toepfer/keyword_if_then_else
Browse files Browse the repository at this point in the history
Keywords if,then and else
  • Loading branch information
sebastian-toepfer authored Jun 15, 2024
2 parents 1001a5a + baadf17 commit 75abb7e
Show file tree
Hide file tree
Showing 21 changed files with 1,083 additions and 118 deletions.
1 change: 1 addition & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<!-- how to validate?
<include>**/tests/draft2020-12/id.json</include>
-->
<include>**/tests/draft2020-12/if-then-else.json</include>
<include>**/tests/draft2020-12/items.json</include>
<include>**/tests/draft2020-12/maxContains.json</include>
<include>**/tests/draft2020-12/maxItems.json</include>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,65 +25,8 @@

import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.UnaryOperator;

public final class AffectedBy implements Comparable<AffectedBy> {

private final AffectByType type;
private final String name;

public AffectedBy(final AffectByType type, final String name) {
this.type = Objects.requireNonNull(type);
this.name = Objects.requireNonNull(name);
}

@Override
public int hashCode() {
int hash = 7;
hash = 83 * hash + Objects.hashCode(this.type);
hash = 83 * hash + Objects.hashCode(this.name);
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;
}
return compareTo((AffectedBy) obj) == 0;
}

@Override
public int compareTo(final AffectedBy other) {
final int result;
if (type.compareTo(other.type) == 0) {
result = name.compareTo(other.name);
} else {
result = type.compareTo(other.type);
}
return result;
}

Function<Keyword, Keyword> findAffectedByKeywordIn(final JsonSchema schema) {
final UnaryOperator<Keyword> result;
if (schema.keywordByName(name).isPresent()) {
result = type::affect;
} else {
result = k -> k;
}
return result;
}

@Override
public String toString() {
return "AffectedBy{" + "type=" + type + ", name=" + name + '}';
}
public interface AffectedBy {
Function<Keyword, Keyword> findAffectedByKeywordIn(JsonSchema schema);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Set;
import java.util.function.Function;

public final class AffectedByKeywordType implements KeywordType {
Expand Down Expand Up @@ -65,7 +64,7 @@ public Keyword createKeyword(final JsonSchema schema) {
static final class AffectedKeyword extends KeywordRelationship {

private final JsonSchema schema;
private final SortedSet<AffectedBy> affectedBy;
private final Set<AffectedBy> affectedBy;
private final Function<JsonSchema, Keyword> keywordCreator;

public AffectedKeyword(
Expand All @@ -76,7 +75,7 @@ public AffectedKeyword(
) {
super(name);
this.schema = Objects.requireNonNull(schema);
this.affectedBy = new TreeSet<>(affectedBy);
this.affectedBy = Set.copyOf(affectedBy);
this.keywordCreator = Objects.requireNonNull(keywordCreator);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* The MIT License
*
* Copyright 2024 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.keyword.type;

import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
import java.util.Objects;
import java.util.function.Function;

public final class ExtendedBy implements AffectedBy {

private final String name;

public ExtendedBy(final String name) {
this.name = name;
}

@Override
public Function<Keyword, Keyword> findAffectedByKeywordIn(final JsonSchema schema) {
return k -> k;
}

@Override
public String toString() {
return "Extends{" + "name=" + name + '}';
}

@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + Objects.hashCode(this.name);
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 ExtendedBy other = (ExtendedBy) obj;
return Objects.equals(this.name, other.name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* The MIT License
*
* Copyright 2024 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.keyword.type;

import jakarta.json.JsonValue;
import java.util.function.Predicate;

public enum LINKTYPE {
VALID {
@Override
Predicate<JsonValue> connect(final Predicate<JsonValue> first, final Predicate<JsonValue> second) {
return first.negate().or(second);
}
},
INVALID {
@Override
Predicate<JsonValue> connect(final Predicate<JsonValue> first, final Predicate<JsonValue> second) {
return first.or(second);
}
};

abstract Predicate<JsonValue> connect(Predicate<JsonValue> first, Predicate<JsonValue> second);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* The MIT License
*
* Copyright 2024 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.keyword.type;

import io.github.sebastiantoepfer.ddd.common.Media;
import io.github.sebastiantoepfer.jsonschema.keyword.Applicator;
import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
import jakarta.json.JsonValue;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;

final class LinkedKeyword implements Applicator {

private final Keyword firstChainLink;
private final LINKTYPE linkType;
private final Keyword secondChanLink;

public LinkedKeyword(final Keyword firstChainLink, final LINKTYPE linkType, final Keyword secondChanLink) {
this.firstChainLink = Objects.requireNonNull(firstChainLink);
this.linkType = Objects.requireNonNull(linkType);
this.secondChanLink = Objects.requireNonNull(secondChanLink);
}

@Override
public Collection<KeywordCategory> categories() {
final Set<KeywordCategory> result = EnumSet.copyOf(firstChainLink.categories());
result.addAll(secondChanLink.categories());
return result;
}

@Override
public boolean applyTo(final JsonValue instance) {
return linkType
.connect(firstChainLink.asApplicator()::applyTo, secondChanLink.asApplicator()::applyTo)
.test(instance);
}

@Override
public boolean hasName(final String name) {
return secondChanLink.hasName(name);
}

@Override
public <T extends Media<T>> T printOn(final T media) {
return secondChanLink.printOn(media);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* The MIT License
*
* Copyright 2024 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.keyword.type;

import io.github.sebastiantoepfer.jsonschema.JsonSchema;
import io.github.sebastiantoepfer.jsonschema.JsonSubSchema;
import io.github.sebastiantoepfer.jsonschema.keyword.Keyword;
import java.util.Objects;
import java.util.function.Function;

public final class LinkedWith implements AffectedBy {

private final String name;
private final Function<JsonSubSchema, Keyword> keywordCreator;
private final LINKTYPE linkType;

public LinkedWith(
final String name,
final Function<JsonSubSchema, Keyword> keywordCreator,
final LINKTYPE linkType
) {
this.name = Objects.requireNonNull(name);
this.keywordCreator = Objects.requireNonNull(keywordCreator);
this.linkType = Objects.requireNonNull(linkType);
}

@Override
public Function<Keyword, Keyword> findAffectedByKeywordIn(final JsonSchema schema) {
return schema
.subSchema(name)
.map(keywordCreator)
.map(k -> (Function<Keyword, Keyword>) new KeywordLink(k, linkType))
.orElse(ReplacingKeyword::new);
}

@Override
public String toString() {
return "LinkedWith{" + "name=" + name + '}';
}

private static class KeywordLink implements Function<Keyword, Keyword> {

private final Keyword firstChainLink;
private final LINKTYPE linkType;

public KeywordLink(final Keyword firstChainLink, final LINKTYPE linkType) {
this.firstChainLink = Objects.requireNonNull(firstChainLink);
this.linkType = Objects.requireNonNull(linkType);
}

@Override
public Keyword apply(final Keyword secondChanLink) {
return new LinkedKeyword(firstChainLink, linkType, secondChanLink);
}
}
}
Loading

0 comments on commit 75abb7e

Please sign in to comment.