|
| 1 | +package org.openapijsonschematools.schemas; |
| 2 | + |
| 3 | +import org.openapijsonschematools.schemas.validators.KeywordValidator; |
| 4 | +import org.openapijsonschematools.schemas.validators.TypeValidator; |
| 5 | + |
| 6 | +import java.lang.reflect.Field; |
| 7 | +import java.util.HashMap; |
| 8 | +import java.util.LinkedHashSet; |
| 9 | +import java.util.Map; |
| 10 | + |
| 11 | +public class SchemaValidator { |
| 12 | + static final HashMap<String, KeywordValidator> keywordToValidator = new HashMap(){{ |
| 13 | + put("type", new TypeValidator()); |
| 14 | + }}; |
| 15 | + static PathToSchemasMap _validate( |
| 16 | + Class<SchemaValidator> cls, |
| 17 | + Object arg, |
| 18 | + ValidationMetadata validationMetadata |
| 19 | + ) throws InstantiationException, IllegalAccessException { |
| 20 | + SchemaValidator clsSchema = cls.newInstance(); |
| 21 | + Field[] fields = cls.getDeclaredFields(); |
| 22 | + HashMap<String, Object> fieldsToValues = new HashMap<>(); |
| 23 | + LinkedHashSet<String> disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords(); |
| 24 | + for (Field field : fields) { |
| 25 | + String fieldName = field.getName(); |
| 26 | + if (disabledKeywords.contains(fieldName)) { |
| 27 | + continue; |
| 28 | + } |
| 29 | + Object value = field.get(clsSchema); |
| 30 | + fieldsToValues.put(fieldName, value); |
| 31 | + } |
| 32 | + PathToSchemasMap pathToSchemas = new PathToSchemasMap(); |
| 33 | + for (Map.Entry<String, Object> entry: fieldsToValues.entrySet()) { |
| 34 | + String jsonKeyword = entry.getKey(); |
| 35 | + Object value = entry.getValue(); |
| 36 | + KeywordValidator validatorClass = keywordToValidator.get(jsonKeyword); |
| 37 | + PathToSchemasMap otherPathToSchemas = validatorClass.validate( |
| 38 | + arg, |
| 39 | + value, |
| 40 | + null, |
| 41 | + cls, |
| 42 | + validationMetadata |
| 43 | + ); |
| 44 | + } |
| 45 | + return pathToSchemas; |
| 46 | + } |
| 47 | +} |
| 48 | +/** |
| 49 | + * @classmethod |
| 50 | + * def _validate( |
| 51 | + * cls, |
| 52 | + * arg, |
| 53 | + * validation_metadata: ValidationMetadata, |
| 54 | + * ) -> PathToSchemasType: |
| 55 | + * """ |
| 56 | + * SchemaValidator validate |
| 57 | + * All keyword validation except for type checking was done in calling stack frames |
| 58 | + * If those validations passed, the validated classes are collected in path_to_schemas |
| 59 | + * """ |
| 60 | + * cls_schema = cls() |
| 61 | + * json_schema_data = { |
| 62 | + * k: v |
| 63 | + * for k, v in vars(cls_schema).items() |
| 64 | + * if k not in cls.__excluded_cls_properties |
| 65 | + * and k |
| 66 | + * not in validation_metadata.configuration.disabled_json_schema_python_keywords |
| 67 | + * } |
| 68 | + * contains_path_to_schemas = [] |
| 69 | + * path_to_schemas: PathToSchemasType = {} |
| 70 | + * if 'contains' in vars(cls_schema): |
| 71 | + * contains_path_to_schemas = _get_contains_path_to_schemas( |
| 72 | + * arg, |
| 73 | + * vars(cls_schema)['contains'], |
| 74 | + * validation_metadata, |
| 75 | + * path_to_schemas |
| 76 | + * ) |
| 77 | + * if_path_to_schemas = None |
| 78 | + * if 'if_' in vars(cls_schema): |
| 79 | + * if_path_to_schemas = _get_if_path_to_schemas( |
| 80 | + * arg, |
| 81 | + * vars(cls_schema)['if_'], |
| 82 | + * validation_metadata, |
| 83 | + * ) |
| 84 | + * validated_pattern_properties: typing.Optional[PathToSchemasType] = None |
| 85 | + * if 'pattern_properties' in vars(cls_schema): |
| 86 | + * validated_pattern_properties = _get_validated_pattern_properties( |
| 87 | + * arg, |
| 88 | + * vars(cls_schema)['pattern_properties'], |
| 89 | + * cls, |
| 90 | + * validation_metadata |
| 91 | + * ) |
| 92 | + * prefix_items_length = 0 |
| 93 | + * if 'prefix_items' in vars(cls_schema): |
| 94 | + * prefix_items_length = len(vars(cls_schema)['prefix_items']) |
| 95 | + * for keyword, val in json_schema_data.items(): |
| 96 | + * used_val: typing.Any |
| 97 | + * if keyword in {'contains', 'min_contains', 'max_contains'}: |
| 98 | + * used_val = (val, contains_path_to_schemas) |
| 99 | + * elif keyword == 'items': |
| 100 | + * used_val = (val, prefix_items_length) |
| 101 | + * elif keyword in {'unevaluated_items', 'unevaluated_properties'}: |
| 102 | + * used_val = (val, path_to_schemas) |
| 103 | + * elif keyword in {'types'}: |
| 104 | + * format: typing.Optional[str] = vars(cls_schema).get('format', None) |
| 105 | + * used_val = (val, format) |
| 106 | + * elif keyword in {'pattern_properties', 'additional_properties'}: |
| 107 | + * used_val = (val, validated_pattern_properties) |
| 108 | + * elif keyword in {'if_', 'then', 'else_'}: |
| 109 | + * used_val = (val, if_path_to_schemas) |
| 110 | + * else: |
| 111 | + * used_val = val |
| 112 | + * validator = json_schema_keyword_to_validator[keyword] |
| 113 | + * |
| 114 | + * other_path_to_schemas = validator( |
| 115 | + * arg, |
| 116 | + * used_val, |
| 117 | + * cls, |
| 118 | + * validation_metadata, |
| 119 | + * |
| 120 | + * ) |
| 121 | + * if other_path_to_schemas: |
| 122 | + * update(path_to_schemas, other_path_to_schemas) |
| 123 | + * |
| 124 | + * base_class = type(arg) |
| 125 | + * if validation_metadata.path_to_item not in path_to_schemas: |
| 126 | + * path_to_schemas[validation_metadata.path_to_item] = dict() |
| 127 | + * path_to_schemas[validation_metadata.path_to_item][base_class] = None |
| 128 | + * path_to_schemas[validation_metadata.path_to_item][cls] = None |
| 129 | + * return path_to_schemas |
| 130 | + */ |
0 commit comments