1 /* 2 * Copyright (c) 2016 Network New Technologies Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.networknt.schema; 18 19 import com.fasterxml.jackson.databind.JsonNode; 20 import com.networknt.schema.SpecVersion.VersionFlag; 21 22 import java.util.ArrayList; 23 import java.util.EnumSet; 24 import java.util.HashMap; 25 import java.util.List; 26 import java.util.Map; 27 28 @FunctionalInterface 29 interface ValidatorFactory { newInstance(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext)30 JsonValidator newInstance(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, 31 JsonSchema parentSchema, ValidationContext validationContext); 32 } 33 34 enum VersionCode { 35 None(new SpecVersion.VersionFlag[] { }), 36 AllVersions(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V4, SpecVersion.VersionFlag.V6, SpecVersion.VersionFlag.V7, SpecVersion.VersionFlag.V201909, SpecVersion.VersionFlag.V202012 }), 37 MinV6(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V6, SpecVersion.VersionFlag.V7, SpecVersion.VersionFlag.V201909, SpecVersion.VersionFlag.V202012 }), 38 MinV6MaxV7(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V6, SpecVersion.VersionFlag.V7 }), 39 MinV7(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V7, SpecVersion.VersionFlag.V201909, SpecVersion.VersionFlag.V202012 }), 40 MaxV7(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V4, SpecVersion.VersionFlag.V6, SpecVersion.VersionFlag.V7 }), 41 MaxV201909(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V4, SpecVersion.VersionFlag.V6, SpecVersion.VersionFlag.V7, SpecVersion.VersionFlag.V201909 }), 42 MinV201909(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V201909, SpecVersion.VersionFlag.V202012 }), 43 MinV202012(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V202012 }), 44 V201909(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V201909 }), 45 V7(new SpecVersion.VersionFlag[] { SpecVersion.VersionFlag.V7 }); 46 47 private final EnumSet<VersionFlag> versions; 48 VersionCode(SpecVersion.VersionFlag[] versionFlags)49 VersionCode(SpecVersion.VersionFlag[] versionFlags) { 50 this.versions = EnumSet.noneOf(VersionFlag.class); 51 for (VersionFlag flag: versionFlags) { 52 this.versions.add(flag); 53 } 54 } 55 getVersions()56 EnumSet<VersionFlag> getVersions() { 57 return this.versions; 58 } 59 } 60 61 public enum ValidatorTypeCode implements Keyword, ErrorMessageType { 62 ADDITIONAL_PROPERTIES("additionalProperties", "1001", AdditionalPropertiesValidator::new, VersionCode.MaxV7), 63 ALL_OF("allOf", "1002", AllOfValidator::new, VersionCode.MaxV7), 64 ANY_OF("anyOf", "1003", AnyOfValidator::new, VersionCode.MaxV7), 65 CONST("const", "1042", ConstValidator::new, VersionCode.MinV6MaxV7), 66 CONTAINS("contains", "1043", ContainsValidator::new, VersionCode.MinV6MaxV7), 67 CONTENT_ENCODING("contentEncoding", "1052", ContentEncodingValidator::new, VersionCode.V7), 68 CONTENT_MEDIA_TYPE("contentMediaType", "1053", ContentMediaTypeValidator::new, VersionCode.V7), 69 DEPENDENCIES("dependencies", "1007", DependenciesValidator::new, VersionCode.AllVersions), 70 DEPENDENT_REQUIRED("dependentRequired", "1045", DependentRequired::new, VersionCode.None), 71 DEPENDENT_SCHEMAS("dependentSchemas", "1046", DependentSchemas::new, VersionCode.None), 72 DISCRIMINATOR("discriminator", "2001", DiscriminatorValidator::new, VersionCode.None), 73 DYNAMIC_REF("$dynamicRef", "1051", DynamicRefValidator::new, VersionCode.None), 74 ENUM("enum", "1008", EnumValidator::new, VersionCode.MaxV7), 75 EXCLUSIVE_MAXIMUM("exclusiveMaximum", "1038", ExclusiveMaximumValidator::new, VersionCode.MinV6MaxV7), 76 EXCLUSIVE_MINIMUM("exclusiveMinimum", "1039", ExclusiveMinimumValidator::new, VersionCode.MinV6MaxV7), 77 FALSE("false", "1041", FalseValidator::new, VersionCode.MinV6), 78 FORMAT("format", "1009", null, VersionCode.MaxV7) { newValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext)79 @Override public JsonValidator newValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) { 80 throw new UnsupportedOperationException("Use FormatKeyword instead"); 81 } 82 }, 83 ID("id", "1036", null, VersionCode.AllVersions), 84 IF_THEN_ELSE("if", "1037", IfValidator::new, VersionCode.V7), 85 ITEMS_202012("items", "1010", ItemsValidator202012::new, VersionCode.None), 86 ITEMS("items", "1010", ItemsValidator::new, VersionCode.MaxV7), 87 MAX_CONTAINS("maxContains", "1006", MinMaxContainsValidator::new, VersionCode.None), 88 MAX_ITEMS("maxItems", "1012", MaxItemsValidator::new, VersionCode.MaxV7), 89 MAX_LENGTH("maxLength", "1013", MaxLengthValidator::new, VersionCode.MaxV7), 90 MAX_PROPERTIES("maxProperties", "1014", MaxPropertiesValidator::new, VersionCode.MaxV7), 91 MAXIMUM("maximum", "1011", MaximumValidator::new, VersionCode.MaxV7), 92 MIN_CONTAINS("minContains", "1049", MinMaxContainsValidator::new, VersionCode.None), 93 MIN_ITEMS("minItems", "1016", MinItemsValidator::new, VersionCode.MaxV7), 94 MIN_LENGTH("minLength", "1017", MinLengthValidator::new, VersionCode.MaxV7), 95 MIN_PROPERTIES("minProperties", "1018", MinPropertiesValidator::new, VersionCode.MaxV7), 96 MINIMUM("minimum", "1015", MinimumValidator::new, VersionCode.MaxV7), 97 MULTIPLE_OF("multipleOf", "1019", MultipleOfValidator::new, VersionCode.MaxV7), 98 NOT_ALLOWED("notAllowed", "1033", NotAllowedValidator::new, VersionCode.AllVersions), 99 NOT("not", "1020", NotValidator::new, VersionCode.MaxV7), 100 ONE_OF("oneOf", "1022", OneOfValidator::new, VersionCode.MaxV7), 101 PATTERN_PROPERTIES("patternProperties", "1024", PatternPropertiesValidator::new, VersionCode.MaxV7), 102 PATTERN("pattern", "1023", PatternValidator::new, VersionCode.MaxV7), 103 PREFIX_ITEMS("prefixItems", "1048", PrefixItemsValidator::new, VersionCode.None), 104 PROPERTIES("properties", "1025", PropertiesValidator::new, VersionCode.MaxV7), 105 PROPERTYNAMES("propertyNames", "1044", PropertyNamesValidator::new, VersionCode.MinV6MaxV7), 106 READ_ONLY("readOnly", "1032", ReadOnlyValidator::new, VersionCode.V7), 107 RECURSIVE_REF("$recursiveRef", "1050", RecursiveRefValidator::new, VersionCode.None), 108 REF("$ref", "1026", RefValidator::new, VersionCode.MaxV7), 109 REQUIRED("required", "1028", RequiredValidator::new, VersionCode.MaxV7), 110 TRUE("true", "1040", TrueValidator::new, VersionCode.MinV6), 111 TYPE("type", "1029", TypeValidator::new, VersionCode.MaxV7), 112 UNEVALUATED_ITEMS("unevaluatedItems", "1021", UnevaluatedItemsValidator::new, VersionCode.None), 113 UNEVALUATED_PROPERTIES("unevaluatedProperties","1047",UnevaluatedPropertiesValidator::new,VersionCode.None), 114 UNION_TYPE("unionType", "1030", UnionTypeValidator::new, VersionCode.None), 115 UNIQUE_ITEMS("uniqueItems", "1031", UniqueItemsValidator::new, VersionCode.MaxV7), 116 WRITE_ONLY("writeOnly", "1027", WriteOnlyValidator::new, VersionCode.V7), 117 ; 118 119 private static final Map<String, ValidatorTypeCode> CONSTANTS = new HashMap<>(); 120 121 static { 122 for (ValidatorTypeCode c : values()) { CONSTANTS.put(c.value, c)123 CONSTANTS.put(c.value, c); 124 } 125 } 126 127 private final String value; 128 private final String errorCode; 129 private final ValidatorFactory validatorFactory; 130 private final VersionCode versionCode; 131 ValidatorTypeCode(String value, String errorCode, ValidatorFactory validatorFactory, VersionCode versionCode)132 private ValidatorTypeCode(String value, String errorCode, ValidatorFactory validatorFactory, VersionCode versionCode) { 133 this.value = value; 134 this.errorCode = errorCode; 135 this.validatorFactory = validatorFactory; 136 this.versionCode = versionCode; 137 } 138 getKeywords(SpecVersion.VersionFlag versionFlag)139 public static List<ValidatorTypeCode> getKeywords(SpecVersion.VersionFlag versionFlag) { 140 final List<ValidatorTypeCode> result = new ArrayList<>(); 141 for (ValidatorTypeCode keyword : values()) { 142 if (keyword.getVersionCode().getVersions().contains(versionFlag)) { 143 result.add(keyword); 144 } 145 } 146 return result; 147 } 148 fromValue(String value)149 public static ValidatorTypeCode fromValue(String value) { 150 ValidatorTypeCode constant = CONSTANTS.get(value); 151 if (constant == null) { 152 throw new IllegalArgumentException(value); 153 } 154 return constant; 155 } 156 157 @Override newValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext)158 public JsonValidator newValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, 159 JsonSchema parentSchema, ValidationContext validationContext) { 160 if (this.validatorFactory == null) { 161 throw new UnsupportedOperationException("No suitable validator for " + getValue()); 162 } 163 return validatorFactory.newInstance(schemaLocation, evaluationPath, schemaNode, parentSchema, 164 validationContext); 165 } 166 167 @Override toString()168 public String toString() { 169 return this.value; 170 } 171 172 @Override getValue()173 public String getValue() { 174 return this.value; 175 } 176 177 @Override getErrorCode()178 public String getErrorCode() { 179 return this.errorCode; 180 } 181 getVersionCode()182 public VersionCode getVersionCode() { 183 return this.versionCode; 184 } 185 186 @Override getErrorCodeValue()187 public String getErrorCodeValue() { 188 return getValue(); 189 } 190 } 191