From ddc946f4b77cffc264d06cbad22817e385f19bde Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 5 Nov 2023 10:20:07 -0800 Subject: [PATCH 01/11] Improves SchemaValidatorTest --- .../schemas/SchemaValidator.java | 9 +++++++++ .../schemas/SchemaValidatorTest.java | 16 +++++++++++++--- .../org/openapitools/schemas/SchemaValidator.hbs | 9 +++++++++ .../openapitools/schemas/SchemaValidatorTest.hbs | 16 +++++++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java index 8439ee4164f..540dba9a1bb 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java @@ -7,6 +7,7 @@ import java.lang.reflect.RecordComponent; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; public interface SchemaValidator { @@ -43,6 +44,14 @@ static PathToSchemasMap _validate( validationMetadata ); } + Class baseClass = arg.getClass(); + List pathToItem = validationMetadata.pathToItem(); + if (!pathToSchemas.containsKey(pathToItem)) { + pathToSchemas.put(validationMetadata.pathToItem(), new HashMap<>()); + } + pathToSchemas.get(pathToItem).put(baseClass, null); + pathToSchemas.get(pathToItem).put(schemaCls, null); + return pathToSchemas; } } diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java index 22b6678d00a..d48105e0d8e 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java @@ -1,12 +1,15 @@ package org.openapijsonschematools.schemas; +import org.junit.Assert; import org.junit.Test; import org.openapijsonschematools.configurations.JsonSchemaKeywordFlags; import org.openapijsonschematools.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; record SomeSchema(LinkedHashSet> type) implements SchemaValidator { static SomeSchema withDefaults() { @@ -31,18 +34,25 @@ static PathToSchemasMap _validate( public class SchemaValidatorTest { - @Test public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + List pathToItem = new ArrayList<>(); + pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( - new ArrayList<>(), + pathToItem, new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()), new PathToSchemasMap(), new LinkedHashSet<>() ); - SomeSchema._validate( + PathToSchemasMap pathToSchemas = SomeSchema._validate( "hi", validationMetadata ); + PathToSchemasMap expectedPathToSchemas = new PathToSchemasMap(); + HashMap, Void> validatedClasses = new HashMap<>(); + validatedClasses.put(SomeSchema.class, null); + validatedClasses.put(String.class, null); + expectedPathToSchemas.put(pathToItem, validatedClasses); + Assert.assertEquals(pathToSchemas, expectedPathToSchemas); } } diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs index 97d417734a1..b294698e48c 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs @@ -7,6 +7,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.RecordComponent; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; public interface SchemaValidator { @@ -43,6 +44,14 @@ public interface SchemaValidator { validationMetadata ); } + Class baseClass = arg.getClass(); + List pathToItem = validationMetadata.pathToItem(); + if (!pathToSchemas.containsKey(pathToItem)) { + pathToSchemas.put(validationMetadata.pathToItem(), new HashMap<>()); + } + pathToSchemas.get(pathToItem).put(baseClass, null); + pathToSchemas.get(pathToItem).put(schemaCls, null); + return pathToSchemas; } } diff --git a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs index aa454c4545f..2c8d6144129 100644 --- a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs +++ b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs @@ -1,12 +1,15 @@ package {{{packageName}}}.schemas; +import org.junit.Assert; import org.junit.Test; import {{{packageName}}}.configurations.JsonSchemaKeywordFlags; import {{{packageName}}}.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.List; record SomeSchema(LinkedHashSet> type) implements SchemaValidator { static SomeSchema withDefaults() { @@ -31,18 +34,25 @@ record SomeSchema(LinkedHashSet> type) implements SchemaValidator { public class SchemaValidatorTest { - @Test public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + List pathToItem = new ArrayList<>(); + pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( - new ArrayList<>(), + pathToItem, new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()), new PathToSchemasMap(), new LinkedHashSet<>() ); - SomeSchema._validate( + PathToSchemasMap pathToSchemas = SomeSchema._validate( "hi", validationMetadata ); + PathToSchemasMap expectedPathToSchemas = new PathToSchemasMap(); + HashMap, Void> validatedClasses = new HashMap<>(); + validatedClasses.put(SomeSchema.class, null); + validatedClasses.put(String.class, null); + expectedPathToSchemas.put(pathToItem, validatedClasses); + Assert.assertEquals(pathToSchemas, expectedPathToSchemas); } } From d9dcb0c80d8d3cd0dcdd741cc42a7c9b6e7ff85f Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 5 Nov 2023 11:03:36 -0800 Subject: [PATCH 02/11] Adds beginning of Schema class --- .../schemas/PathToTypeMap.java | 8 + .../schemas/Schema.java | 393 ++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToTypeMap.java create mode 100644 samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToTypeMap.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToTypeMap.java new file mode 100644 index 00000000000..9aba997ddaa --- /dev/null +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToTypeMap.java @@ -0,0 +1,8 @@ +package org.openapijsonschematools.schemas; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PathToTypeMap extends HashMap, Class> { +} \ No newline at end of file diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java new file mode 100644 index 00000000000..470842281c3 --- /dev/null +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -0,0 +1,393 @@ +package org.openapijsonschematools.schemas; + +import org.openapijsonschematools.configurations.SchemaConfiguration; + +import java.math.BigDecimal; +import java.nio.file.Path; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public interface Schema extends SchemaValidator { + static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { + RuntimeException strTypeError = new RuntimeException("Invalid type. Required value type is str and passed type was {type(arg)} at {path_to_item}"); + if (arg == null) { + pathToType.put(pathToItem, Void.class); + return null; + } else if (arg instanceof String) { + pathToType.put(pathToItem, String.class); + return (String) arg; + } else if (arg instanceof Map) { + pathToType.put(pathToItem, Map.class); + LinkedHashMap argFixed = new LinkedHashMap<>(); + for (Map.Entry entry: ((Map) arg).entrySet()) { + String key = (String) entry.getKey(); + Object val = entry.getValue(); + List newPathToItem = new ArrayList<>(); + newPathToItem.addAll(pathToItem); + newPathToItem.add(key); + Object fixedVal = castToAllowedTypes(val, newPathToItem, pathToType); + argFixed.put(key, fixedVal); + } + return argFixed; + } else if (arg instanceof Boolean) { + pathToType.put(pathToItem, Boolean.class); + return (Boolean) arg; + } else if (arg instanceof Integer) { + pathToType.put(pathToItem, Integer.class); + return (Integer) arg; + } else if (arg instanceof Float) { + pathToType.put(pathToItem, Float.class); + return (Float) arg; + } else if (arg instanceof Double) { + pathToType.put(pathToItem, Double.class); + return (Double) arg; + } else if (arg instanceof BigDecimal) { + pathToType.put(pathToItem, BigDecimal.class); + return (BigDecimal) arg; + } else if (arg instanceof List) { + pathToType.put(pathToItem, List.class); + List argFixed = new ArrayList<>(); + int i =0; + for (Object item: ((List) arg).toArray()) { + List newPathToItem = new ArrayList<>(); + newPathToItem.addAll(pathToItem); + newPathToItem.add(i); + Object fixedVal = castToAllowedTypes(item, newPathToItem, pathToType); + argFixed.add(fixedVal); + i += 1; + } + return argFixed; + } else if (arg instanceof ZonedDateTime) { + pathToType.put(pathToItem, String.class); + return arg.toString(); + } else if (arg instanceof LocalDate) { + pathToType.put(pathToItem, String.class); + return arg.toString(); + } else { + Class argClass = arg.getClass(); + throw new RuntimeException("Invalid type passed in got input="+arg+" type="+argClass); + } + } + + static Object validateBase(Class cls, Object arg, SchemaConfiguration configuration) { + if (arg instanceof Map || arg instanceof List) { + // todo + } + // todo cast to allowed types + PathToTypeMap pathToType = new PathToTypeMap(); + List pathToItem = new ArrayList<>(); + pathToItem.add("args[0]"); + Object castArg = castToAllowedTypes(arg, pathToItem, pathToType); + return null; + } + /** + * if isinstance(arg, (tuple, validation.immutabledict)): + * type_to_output_cls = cls.__get_type_to_output_cls() + * if type_to_output_cls is not None: + * for output_cls in type_to_output_cls.values(): + * if isinstance(arg, output_cls): + * # U + T use case, don't run validations twice + * return arg + * + * from_server = False + * validated_path_to_schemas: typing.Dict[ + * typing.Tuple[typing.Union[str, int], ...], + * typing.Set[typing.Union[str, int, float, bool, None, validation.immutabledict, tuple]] + * ] = {} + * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], type] = {} + * cast_arg = cast_to_allowed_types( + * arg, from_server, validated_path_to_schemas, ('args[0]',), path_to_type) + * validation_metadata = validation.ValidationMetadata( + * path_to_item=('args[0]',), + * configuration=configuration or schema_configuration.SchemaConfiguration(), + * validated_path_to_schemas=validation.immutabledict(validated_path_to_schemas) + * ) + * path_to_schemas = cls.__get_path_to_schemas(cast_arg, validation_metadata, path_to_type) + * return cls._get_new_instance_without_conversion( + * cast_arg, + * validation_metadata.path_to_item, + * path_to_schemas, + * ) + */ + +} +/** + * class Schema(typing.Generic[T, U], validation.SchemaValidator, metaclass=SingletonMeta): + * + * @classmethod + * def __get_path_to_schemas( + * cls, + * arg, + * validation_metadata: validation.ValidationMetadata, + * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type] + * ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]]: + * """ + * Run all validations in the json schema and return a dict of + * json schema to tuple of validated schemas + * """ + * _path_to_schemas: validation.PathToSchemasType = {} + * if validation_metadata.validation_ran_earlier(cls): + * validation.add_deeper_validated_schemas(validation_metadata, _path_to_schemas) + * else: + * other_path_to_schemas = cls._validate(arg, validation_metadata=validation_metadata) + * validation.update(_path_to_schemas, other_path_to_schemas) + * # loop through it make a new class for each entry + * # do not modify the returned result because it is cached and we would be modifying the cached value + * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] = {} + * for path, schema_classes in _path_to_schemas.items(): + * schema = typing.cast(typing.Type[Schema], tuple(schema_classes)[-1]) + * path_to_schemas[path] = schema + * """ + * For locations that validation did not check + * the code still needs to store type + schema information for instantiation + * All of those schemas will be UnsetAnyTypeSchema + * """ + * missing_paths = path_to_type.keys() - path_to_schemas.keys() + * for missing_path in missing_paths: + * path_to_schemas[missing_path] = UnsetAnyTypeSchema + * + * return path_to_schemas + * + * @staticmethod + * def __get_items( + * arg: tuple, + * path_to_item: typing.Tuple[typing.Union[str, int], ...], + * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] + * ): + * ''' + * Schema __get_items + * ''' + * cast_items = [] + * + * for i, value in enumerate(arg): + * item_path_to_item = path_to_item + (i,) + * item_cls = path_to_schemas[item_path_to_item] + * new_value = item_cls._get_new_instance_without_conversion( + * value, + * item_path_to_item, + * path_to_schemas + * ) + * cast_items.append(new_value) + * + * return tuple(cast_items) + * + * @staticmethod + * def __get_properties( + * arg: validation.immutabledict[str, typing.Any], + * path_to_item: typing.Tuple[typing.Union[str, int], ...], + * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] + * ): + * """ + * Schema __get_properties, this is how properties are set + * These values already passed validation + * """ + * dict_items = {} + * + * for property_name_js, value in arg.items(): + * property_path_to_item = path_to_item + (property_name_js,) + * property_cls = path_to_schemas[property_path_to_item] + * new_value = property_cls._get_new_instance_without_conversion( + * value, + * property_path_to_item, + * path_to_schemas + * ) + * dict_items[property_name_js] = new_value + * + * return validation.immutabledict(dict_items) + * + * @classmethod + * def _get_new_instance_without_conversion( + * cls, + * arg: typing.Union[int, float, None, Bool, str, validation.immutabledict, tuple, FileIO, bytes], + * path_to_item: typing.Tuple[typing.Union[str, int], ...], + * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] + * ): + * # We have a Dynamic class and we are making an instance of it + * if isinstance(arg, validation.immutabledict): + * used_arg = cls.__get_properties(arg, path_to_item, path_to_schemas) + * elif isinstance(arg, tuple): + * used_arg = cls.__get_items(arg, path_to_item, path_to_schemas) + * elif isinstance(arg, Bool): + * return bool(arg) + * else: + * """ + * str, int, float, FileIO, bytes + * FileIO = openapi binary type and the user inputs a file + * bytes = openapi binary type and the user inputs bytes + * """ + * return arg + * arg_type = type(arg) + * type_to_output_cls = cls.__get_type_to_output_cls() + * if type_to_output_cls is None: + * return used_arg + * if arg_type not in type_to_output_cls: + * return used_arg + * output_cls = type_to_output_cls[arg_type] + * if arg_type is tuple: + * inst = super(output_cls, output_cls).__new__(output_cls, used_arg) # type: ignore + * inst = typing.cast(U, inst) + * return inst + * assert issubclass(output_cls, validation.immutabledict) + * inst = super(output_cls, output_cls).__new__(output_cls, used_arg) # type: ignore + * inst = typing.cast(T, inst) + * return inst + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: None, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> None: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Literal[True], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> typing.Literal[True]: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Literal[False], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> typing.Literal[False]: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: bool, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> bool: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: int, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> int: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: float, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> float: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Union[str, datetime.date, datetime.datetime, uuid.UUID], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> str: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: SequenceNotStr[INPUT_TYPES_ALL], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> U: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: U, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> U: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Mapping[str, object], # object needed as value type for typeddict inputs + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> T: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Union[ + * typing.Mapping[str, INPUT_TYPES_ALL], + * T + * ], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> T: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: typing.Union[io.FileIO, io.BufferedReader], + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> FileIO: ... + * + * @typing.overload + * @classmethod + * def validate_base( + * cls, + * arg: bytes, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + * ) -> bytes: ... + * + * @classmethod + * def validate_base( + * cls, + * arg, + * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None, + * ): + * """ + * Schema validate_base + * + * Args: + * arg (int/float/str/list/tuple/dict/validation.immutabledict/bool/None): the value + * configuration: contains the schema_configuration.SchemaConfiguration that enables json schema validation keywords + * like minItems, minLength etc + * """ + * if isinstance(arg, (tuple, validation.immutabledict)): + * type_to_output_cls = cls.__get_type_to_output_cls() + * if type_to_output_cls is not None: + * for output_cls in type_to_output_cls.values(): + * if isinstance(arg, output_cls): + * # U + T use case, don't run validations twice + * return arg + * + * from_server = False + * validated_path_to_schemas: typing.Dict[ + * typing.Tuple[typing.Union[str, int], ...], + * typing.Set[typing.Union[str, int, float, bool, None, validation.immutabledict, tuple]] + * ] = {} + * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], type] = {} + * cast_arg = cast_to_allowed_types( + * arg, from_server, validated_path_to_schemas, ('args[0]',), path_to_type) + * validation_metadata = validation.ValidationMetadata( + * path_to_item=('args[0]',), + * configuration=configuration or schema_configuration.SchemaConfiguration(), + * validated_path_to_schemas=validation.immutabledict(validated_path_to_schemas) + * ) + * path_to_schemas = cls.__get_path_to_schemas(cast_arg, validation_metadata, path_to_type) + * return cls._get_new_instance_without_conversion( + * cast_arg, + * validation_metadata.path_to_item, + * path_to_schemas, + * ) + * + * @classmethod + * def __get_type_to_output_cls(cls) -> typing.Optional[typing.Mapping[type, type]]: + * type_to_output_cls = getattr(cls(), 'type_to_output_cls', None) + * type_to_output_cls = typing.cast(typing.Optional[typing.Mapping[type, type]], type_to_output_cls) + * return type_to_output_cls + */ \ No newline at end of file From 2d723b88b7f3922ca6b3c661d21f742c04ff5674 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 5 Nov 2023 11:04:13 -0800 Subject: [PATCH 03/11] Removes unused exception --- .../src/main/java/org/openapijsonschematools/schemas/Schema.java | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index 470842281c3..025b3254cd8 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -13,7 +13,6 @@ public interface Schema extends SchemaValidator { static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { - RuntimeException strTypeError = new RuntimeException("Invalid type. Required value type is str and passed type was {type(arg)} at {path_to_item}"); if (arg == null) { pathToType.put(pathToItem, Void.class); return null; From 68cbca3b3d8fd18ac32bc0426c4029529ae0e8b0 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 5 Nov 2023 12:21:47 -0800 Subject: [PATCH 04/11] Updates SchemaValidator _validate method --- .../schemas/Schema.java | 96 ++++++++++++------- .../schemas/SchemaValidator.java | 13 ++- .../schemas/SchemaValidatorTest.java | 31 +++--- .../openapitools/schemas/SchemaValidator.hbs | 13 ++- 4 files changed, 101 insertions(+), 52 deletions(-) diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index 025b3254cd8..f471246a41e 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -1,13 +1,15 @@ package org.openapijsonschematools.schemas; +import org.openapijsonschematools.configurations.JsonSchemaKeywordFlags; import org.openapijsonschematools.configurations.SchemaConfiguration; +import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; -import java.nio.file.Path; import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -72,46 +74,76 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType } } + static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { + PathToSchemasMap pathToSchemasMap = new PathToSchemasMap(); + if (validationMetadata.validationRanEarlier(cls)) { + // todo add deeper validated schemas + } else { + try { + PathToSchemasMap otherPathToSchemas = SchemaValidator._validate(cls, arg, validationMetadata); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + // todo add remainder + } + return pathToSchemasMap; + /** + * _path_to_schemas: validation.PathToSchemasType = {} + * if validation_metadata.validation_ran_earlier(cls): + * validation.add_deeper_validated_schemas(validation_metadata, _path_to_schemas) + * else: + * other_path_to_schemas = cls._validate(arg, validation_metadata=validation_metadata) + * validation.update(_path_to_schemas, other_path_to_schemas) + * # loop through it make a new class for each entry + * # do not modify the returned result because it is cached and we would be modifying the cached value + * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] = {} + * for path, schema_classes in _path_to_schemas.items(): + * schema = typing.cast(typing.Type[Schema], tuple(schema_classes)[-1]) + * path_to_schemas[path] = schema + * """ + * For locations that validation did not check + * the code still needs to store type + schema information for instantiation + * All of those schemas will be UnsetAnyTypeSchema + * """ + * missing_paths = path_to_type.keys() - path_to_schemas.keys() + * for missing_path in missing_paths: + * path_to_schemas[missing_path] = UnsetAnyTypeSchema + * + * return path_to_schemas + */ + } + + static Object getNewInstance(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + return null; + } + + static Object validateBase(Class cls, Object arg, SchemaConfiguration configuration) { if (arg instanceof Map || arg instanceof List) { // todo } - // todo cast to allowed types PathToTypeMap pathToType = new PathToTypeMap(); List pathToItem = new ArrayList<>(); pathToItem.add("args[0]"); Object castArg = castToAllowedTypes(arg, pathToItem, pathToType); - return null; + SchemaConfiguration usedConfiguration; + if (configuration != null) { + usedConfiguration = configuration; + } else { + usedConfiguration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); + } + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata( + pathToItem, + usedConfiguration, + validatedPathToSchemas, + new LinkedHashSet<>() + ); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(cls, castArg, validationMetadata, pathToType); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); } - /** - * if isinstance(arg, (tuple, validation.immutabledict)): - * type_to_output_cls = cls.__get_type_to_output_cls() - * if type_to_output_cls is not None: - * for output_cls in type_to_output_cls.values(): - * if isinstance(arg, output_cls): - * # U + T use case, don't run validations twice - * return arg - * - * from_server = False - * validated_path_to_schemas: typing.Dict[ - * typing.Tuple[typing.Union[str, int], ...], - * typing.Set[typing.Union[str, int, float, bool, None, validation.immutabledict, tuple]] - * ] = {} - * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], type] = {} - * cast_arg = cast_to_allowed_types( - * arg, from_server, validated_path_to_schemas, ('args[0]',), path_to_type) - * validation_metadata = validation.ValidationMetadata( - * path_to_item=('args[0]',), - * configuration=configuration or schema_configuration.SchemaConfiguration(), - * validated_path_to_schemas=validation.immutabledict(validated_path_to_schemas) - * ) - * path_to_schemas = cls.__get_path_to_schemas(cast_arg, validation_metadata, path_to_type) - * return cls._get_new_instance_without_conversion( - * cast_arg, - * validation_metadata.path_to_item, - * path_to_schemas, - * ) - */ } /** diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java index 540dba9a1bb..f1ad528348d 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java @@ -14,14 +14,20 @@ public interface SchemaValidator { static final HashMap keywordToValidator = new HashMap(){{ put("type", new TypeValidator()); }}; + static PathToSchemasMap _validate( - SchemaValidator schema, + Class schemaCls, Object arg, ValidationMetadata validationMetadata ) throws InvocationTargetException, IllegalAccessException { HashMap fieldsToValues = new HashMap<>(); + SchemaValidator schema = null; + try { + schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } LinkedHashSet disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords(); - Class schemaCls = (Class) schema.getClass(); RecordComponent[] recordComponents = schemaCls.getRecordComponents(); for (RecordComponent recordComponent : recordComponents) { String fieldName = recordComponent.getName(); @@ -32,6 +38,7 @@ static PathToSchemasMap _validate( fieldsToValues.put(fieldName, value); } PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + Class castSchemaCls = (Class) schemaCls; for (Map.Entry entry: fieldsToValues.entrySet()) { String jsonKeyword = entry.getKey(); Object value = entry.getValue(); @@ -40,7 +47,7 @@ static PathToSchemasMap _validate( arg, value, null, - schemaCls, + castSchemaCls, validationMetadata ); } diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java index d48105e0d8e..51cc91ca1dd 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java @@ -6,36 +6,38 @@ import org.openapijsonschematools.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; record SomeSchema(LinkedHashSet> type) implements SchemaValidator { - static SomeSchema withDefaults() { + public static SomeSchema withDefaults() { LinkedHashSet> type = new LinkedHashSet<>(); type.add(String.class); return new SomeSchema(type); } - static PathToSchemasMap _validate( - Object arg, - ValidationMetadata validationMetadata - ) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return SchemaValidator._validate( - SomeSchema.withDefaults(), - arg, - validationMetadata - ); - } - - +// static PathToSchemasMap _validate( +// Object arg, +// ValidationMetadata validationMetadata +// ) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { +// return SchemaValidator._validate( +// SomeSchema.class, +// arg, +// validationMetadata +// ); +// } } public class SchemaValidatorTest { @Test public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + Class cls = SomeSchema.class; + Method method = cls.getMethod("withDefaults"); + SomeSchema schema = (SomeSchema) method.invoke(null); List pathToItem = new ArrayList<>(); pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( @@ -44,7 +46,8 @@ public void testValidateSucceeds() throws InstantiationException, IllegalAccessE new PathToSchemasMap(), new LinkedHashSet<>() ); - PathToSchemasMap pathToSchemas = SomeSchema._validate( + PathToSchemasMap pathToSchemas = SchemaValidator._validate( + SomeSchema.class, "hi", validationMetadata ); diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs index b294698e48c..2cacdf30613 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs @@ -14,14 +14,20 @@ public interface SchemaValidator { static final HashMap keywordToValidator = new HashMap()\{{ put("type", new TypeValidator()); }}; + static PathToSchemasMap _validate( - SchemaValidator schema, + Class schemaCls, Object arg, ValidationMetadata validationMetadata ) throws InvocationTargetException, IllegalAccessException { HashMap fieldsToValues = new HashMap<>(); + SchemaValidator schema = null; + try { + schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } LinkedHashSet disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords(); - Class schemaCls = (Class) schema.getClass(); RecordComponent[] recordComponents = schemaCls.getRecordComponents(); for (RecordComponent recordComponent : recordComponents) { String fieldName = recordComponent.getName(); @@ -32,6 +38,7 @@ public interface SchemaValidator { fieldsToValues.put(fieldName, value); } PathToSchemasMap pathToSchemas = new PathToSchemasMap(); + Class castSchemaCls = (Class) schemaCls; for (Map.Entry entry: fieldsToValues.entrySet()) { String jsonKeyword = entry.getKey(); Object value = entry.getValue(); @@ -40,7 +47,7 @@ public interface SchemaValidator { arg, value, null, - schemaCls, + castSchemaCls, validationMetadata ); } From e632f84a264d5e63ee3d799325a2ad8e15186ea7 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 5 Nov 2023 12:29:04 -0800 Subject: [PATCH 05/11] Defines _validate only in SchemaValidator --- .../schemas/SchemaValidatorTest.java | 14 -------------- .../openapitools/schemas/SchemaValidatorTest.hbs | 16 ++-------------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java index 51cc91ca1dd..d5905d10564 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java @@ -18,26 +18,12 @@ public static SomeSchema withDefaults() { type.add(String.class); return new SomeSchema(type); } - -// static PathToSchemasMap _validate( -// Object arg, -// ValidationMetadata validationMetadata -// ) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { -// return SchemaValidator._validate( -// SomeSchema.class, -// arg, -// validationMetadata -// ); -// } } public class SchemaValidatorTest { @Test public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - Class cls = SomeSchema.class; - Method method = cls.getMethod("withDefaults"); - SomeSchema schema = (SomeSchema) method.invoke(null); List pathToItem = new ArrayList<>(); pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( diff --git a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs index 2c8d6144129..876e041689f 100644 --- a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs +++ b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs @@ -17,19 +17,6 @@ record SomeSchema(LinkedHashSet> type) implements SchemaValidator { type.add(String.class); return new SomeSchema(type); } - - static PathToSchemasMap _validate( - Object arg, - ValidationMetadata validationMetadata - ) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - return SchemaValidator._validate( - SomeSchema.withDefaults(), - arg, - validationMetadata - ); - } - - } public class SchemaValidatorTest { @@ -44,7 +31,8 @@ public class SchemaValidatorTest { new PathToSchemasMap(), new LinkedHashSet<>() ); - PathToSchemasMap pathToSchemas = SomeSchema._validate( + PathToSchemasMap pathToSchemas = SchemaValidator._validate( + SomeSchema.class, "hi", validationMetadata ); From 6e75be3264776c5d99a67a19186e01e205852580 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 13:49:35 -0800 Subject: [PATCH 06/11] Adds more schema code, adds anytypeschema and unsetanytypeschema --- .../petstore/java/.openapi-generator/FILES | 4 + .../schemas/AnyTypeSchema.java | 54 +++ .../schemas/PathToSchemasMap.java | 16 +- .../schemas/Schema.java | 444 +++++------------- .../schemas/SchemaValidator.java | 3 +- .../schemas/UnsetAnyTypeSchema.java | 54 +++ .../schemas/SchemaValidatorTest.java | 5 +- .../generators/JavaClientGenerator.java | 33 +- .../openapitools/schemas/AnyTypeSchema.hbs | 54 +++ .../openapitools/schemas/PathToSchemasMap.hbs | 16 +- .../openapitools/schemas/PathToTypeMap.hbs | 8 + .../java/org/openapitools/schemas/Schema.hbs | 238 ++++++++++ .../openapitools/schemas/SchemaValidator.hbs | 9 +- .../schemas/UnsetAnyTypeSchema.hbs | 54 +++ .../schemas/SchemaValidatorTest.hbs | 6 +- 15 files changed, 660 insertions(+), 338 deletions(-) create mode 100644 samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java create mode 100644 samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java create mode 100644 src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs create mode 100644 src/main/resources/java/src/main/java/org/openapitools/schemas/PathToTypeMap.hbs create mode 100644 src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs create mode 100644 src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs diff --git a/samples/client/petstore/java/.openapi-generator/FILES b/samples/client/petstore/java/.openapi-generator/FILES index 29549829b4e..b4ec78422d8 100644 --- a/samples/client/petstore/java/.openapi-generator/FILES +++ b/samples/client/petstore/java/.openapi-generator/FILES @@ -2,9 +2,13 @@ README.md pom.xml src/main/java/org/openapijsonschematools/configurations/JsonSchemaKeywordFlags.java src/main/java/org/openapijsonschematools/configurations/SchemaConfiguration.java +src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java src/main/java/org/openapijsonschematools/schemas/CustomIsoparser.java src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java +src/main/java/org/openapijsonschematools/schemas/PathToTypeMap.java +src/main/java/org/openapijsonschematools/schemas/Schema.java src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java src/main/java/org/openapijsonschematools/schemas/ValidationMetadata.java src/main/java/org/openapijsonschematools/schemas/validators/KeywordValidator.java src/main/java/org/openapijsonschematools/schemas/validators/TypeValidator.java diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java new file mode 100644 index 00000000000..f98510dc77c --- /dev/null +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java @@ -0,0 +1,54 @@ +package org.openapijsonschematools.schemas; + +import org.openapijsonschematools.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; + +record AnyTypeSchema() implements Schema { + public static AnyTypeSchema withDefaults() { + return new AnyTypeSchema(); + } + + public static Void validate(Void arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Integer validate(Integer arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Float validate(Float arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Double validate(Double arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(String arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(LocalDate arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static T validate(T arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static U validate(U arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } +} diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java index 915813b0f6f..9c9b9465998 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java @@ -1,8 +1,20 @@ package org.openapijsonschematools.schemas; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public class PathToSchemasMap extends HashMap, Map, Void>> { +public class PathToSchemasMap extends LinkedHashMap, LinkedHashMap, Void>> { + + public void update(PathToSchemasMap other) { + for (Map.Entry, LinkedHashMap, Void>> entry: other.entrySet()) { + List pathToItem = entry.getKey(); + LinkedHashMap, Void> otherSchemas = entry.getValue(); + if (containsKey(pathToItem)) { + get(pathToItem).putAll(otherSchemas); + } else { + put(pathToItem, otherSchemas); + } + } + } } \ No newline at end of file diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index f471246a41e..851bb5e27c7 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -4,16 +4,19 @@ import org.openapijsonschematools.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; -public interface Schema extends SchemaValidator { +public interface Schema extends SchemaValidator { static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { if (arg == null) { pathToType.put(pathToItem, Void.class); @@ -27,8 +30,7 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType for (Map.Entry entry: ((Map) arg).entrySet()) { String key = (String) entry.getKey(); Object val = entry.getValue(); - List newPathToItem = new ArrayList<>(); - newPathToItem.addAll(pathToItem); + List newPathToItem = new ArrayList<>(pathToItem); newPathToItem.add(key); Object fixedVal = castToAllowedTypes(val, newPathToItem, pathToType); argFixed.put(key, fixedVal); @@ -54,8 +56,7 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType List argFixed = new ArrayList<>(); int i =0; for (Object item: ((List) arg).toArray()) { - List newPathToItem = new ArrayList<>(); - newPathToItem.addAll(pathToItem); + List newPathToItem = new ArrayList<>(pathToItem); newPathToItem.add(i); Object fixedVal = castToAllowedTypes(item, newPathToItem, pathToType); argFixed.add(fixedVal); @@ -81,48 +82,137 @@ static PathToSchemasMap getPathToSchemas(Class cls, Object arg, Validati } else { try { PathToSchemasMap otherPathToSchemas = SchemaValidator._validate(cls, arg, validationMetadata); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { + pathToSchemasMap.update(otherPathToSchemas); + } catch (InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } - // todo add remainder + for (LinkedHashMap, Void> schemas: pathToSchemasMap.values()) { + Class firstSchema = schemas.entrySet().iterator().next().getKey(); + schemas.clear(); + schemas.put(firstSchema, null); + } + Set> missingPaths = new HashSet<>(pathToType.keySet()); + missingPaths.removeAll(pathToSchemasMap.keySet()); + if (!missingPaths.isEmpty()) { + LinkedHashMap, Void> unsetAnyTypeSchema = new LinkedHashMap<>(); + unsetAnyTypeSchema.put(UnsetAnyTypeSchema.class, null); + for (List pathToItem: missingPaths) { + pathToSchemasMap.put(pathToItem, unsetAnyTypeSchema); + } + } } return pathToSchemasMap; - /** - * _path_to_schemas: validation.PathToSchemasType = {} - * if validation_metadata.validation_ran_earlier(cls): - * validation.add_deeper_validated_schemas(validation_metadata, _path_to_schemas) - * else: - * other_path_to_schemas = cls._validate(arg, validation_metadata=validation_metadata) - * validation.update(_path_to_schemas, other_path_to_schemas) - * # loop through it make a new class for each entry - * # do not modify the returned result because it is cached and we would be modifying the cached value - * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] = {} - * for path, schema_classes in _path_to_schemas.items(): - * schema = typing.cast(typing.Type[Schema], tuple(schema_classes)[-1]) - * path_to_schemas[path] = schema - * """ - * For locations that validation did not check - * the code still needs to store type + schema information for instantiation - * All of those schemas will be UnsetAnyTypeSchema - * """ - * missing_paths = path_to_type.keys() - path_to_schemas.keys() - * for missing_path in missing_paths: - * path_to_schemas[missing_path] = UnsetAnyTypeSchema - * - * return path_to_schemas - */ } - static Object getNewInstance(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + Map castArg = (Map) arg; + for(Map.Entry entry: castArg.entrySet()) { + String propertyName = entry.getKey(); + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Class propertyClass = (Class) pathToSchemas.get(propertyPathToItem).entrySet().iterator().next().getKey(); + Object value = entry.getValue(); + Object castValue = getNewInstance(propertyClass, value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, castValue); + } + return properties; + } + + static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + ArrayList items = new ArrayList<>(); + List castItems = (List) arg; + int i = 0; + for (Object item: items) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + Class itemClass = (Class) pathToSchemas.get(itemPathToItem).entrySet().iterator().next().getKey(); + Object castItem = getNewInstance(itemClass, item, itemPathToItem, pathToSchemas); + items.add(castItem); + i += 1; + } + return items; + } + + static Map, Class> getTypeToOutputClass(Class cls) { + try { + // This must be implemented in Schemas that are generics as a static method + Method method = cls.getMethod("typeToOutputClass"); + Map, Class> typeToOutputClass = (Map, Class>) method.invoke(null); + return typeToOutputClass; + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + return null; + } + } + + static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + Object usedArg; + if (arg instanceof Map) { + usedArg = getProperties(arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + usedArg = getItems(arg, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + return (Boolean) arg; + } else { + // str, int, float, FileIO, bytes + return arg; + } + Class argType = arg.getClass(); + Map, Class> typeToOutputClass = getTypeToOutputClass(cls); + if (typeToOutputClass == null) { + return usedArg; + } + Class outputClass = typeToOutputClass.get(argType); + // TODO add class instantiation here return null; } + public static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { + return (Void) validateObjectBase(cls, arg, configuration); + } + + public static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { + return (Boolean) validateObjectBase(cls, arg, configuration); + } + + public static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { + return (Integer) validateObjectBase(cls, arg, configuration); + } + + public static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { + return (Float) validateObjectBase(cls, arg, configuration); + } + + public static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { + return (Double) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { + return (T) validateObjectBase(cls, arg, configuration); + } + + public static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { + return (U) validateObjectBase(cls, arg, configuration); + } + + // todo add bytes and FileIO - static Object validateBase(Class cls, Object arg, SchemaConfiguration configuration) { + private static Object validateObjectBase(Class cls, Object arg, SchemaConfiguration configuration) { + Class castCls = (Class) cls; if (arg instanceof Map || arg instanceof List) { - // todo + // todo don't run validation if the instance is one of the class generic types } PathToTypeMap pathToType = new PathToTypeMap(); List pathToItem = new ArrayList<>(); @@ -141,284 +231,8 @@ static Object validateBase(Class cls, Object arg, SchemaConfiguration co validatedPathToSchemas, new LinkedHashSet<>() ); - PathToSchemasMap pathToSchemasMap = getPathToSchemas(cls, castArg, validationMetadata, pathToType); - return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(castCls, castArg, validationMetadata, pathToType); + return getNewInstance(castCls, castArg, validationMetadata.pathToItem(), pathToSchemasMap); } -} -/** - * class Schema(typing.Generic[T, U], validation.SchemaValidator, metaclass=SingletonMeta): - * - * @classmethod - * def __get_path_to_schemas( - * cls, - * arg, - * validation_metadata: validation.ValidationMetadata, - * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type] - * ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]]: - * """ - * Run all validations in the json schema and return a dict of - * json schema to tuple of validated schemas - * """ - * _path_to_schemas: validation.PathToSchemasType = {} - * if validation_metadata.validation_ran_earlier(cls): - * validation.add_deeper_validated_schemas(validation_metadata, _path_to_schemas) - * else: - * other_path_to_schemas = cls._validate(arg, validation_metadata=validation_metadata) - * validation.update(_path_to_schemas, other_path_to_schemas) - * # loop through it make a new class for each entry - * # do not modify the returned result because it is cached and we would be modifying the cached value - * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] = {} - * for path, schema_classes in _path_to_schemas.items(): - * schema = typing.cast(typing.Type[Schema], tuple(schema_classes)[-1]) - * path_to_schemas[path] = schema - * """ - * For locations that validation did not check - * the code still needs to store type + schema information for instantiation - * All of those schemas will be UnsetAnyTypeSchema - * """ - * missing_paths = path_to_type.keys() - path_to_schemas.keys() - * for missing_path in missing_paths: - * path_to_schemas[missing_path] = UnsetAnyTypeSchema - * - * return path_to_schemas - * - * @staticmethod - * def __get_items( - * arg: tuple, - * path_to_item: typing.Tuple[typing.Union[str, int], ...], - * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] - * ): - * ''' - * Schema __get_items - * ''' - * cast_items = [] - * - * for i, value in enumerate(arg): - * item_path_to_item = path_to_item + (i,) - * item_cls = path_to_schemas[item_path_to_item] - * new_value = item_cls._get_new_instance_without_conversion( - * value, - * item_path_to_item, - * path_to_schemas - * ) - * cast_items.append(new_value) - * - * return tuple(cast_items) - * - * @staticmethod - * def __get_properties( - * arg: validation.immutabledict[str, typing.Any], - * path_to_item: typing.Tuple[typing.Union[str, int], ...], - * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] - * ): - * """ - * Schema __get_properties, this is how properties are set - * These values already passed validation - * """ - * dict_items = {} - * - * for property_name_js, value in arg.items(): - * property_path_to_item = path_to_item + (property_name_js,) - * property_cls = path_to_schemas[property_path_to_item] - * new_value = property_cls._get_new_instance_without_conversion( - * value, - * property_path_to_item, - * path_to_schemas - * ) - * dict_items[property_name_js] = new_value - * - * return validation.immutabledict(dict_items) - * - * @classmethod - * def _get_new_instance_without_conversion( - * cls, - * arg: typing.Union[int, float, None, Bool, str, validation.immutabledict, tuple, FileIO, bytes], - * path_to_item: typing.Tuple[typing.Union[str, int], ...], - * path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type[Schema]] - * ): - * # We have a Dynamic class and we are making an instance of it - * if isinstance(arg, validation.immutabledict): - * used_arg = cls.__get_properties(arg, path_to_item, path_to_schemas) - * elif isinstance(arg, tuple): - * used_arg = cls.__get_items(arg, path_to_item, path_to_schemas) - * elif isinstance(arg, Bool): - * return bool(arg) - * else: - * """ - * str, int, float, FileIO, bytes - * FileIO = openapi binary type and the user inputs a file - * bytes = openapi binary type and the user inputs bytes - * """ - * return arg - * arg_type = type(arg) - * type_to_output_cls = cls.__get_type_to_output_cls() - * if type_to_output_cls is None: - * return used_arg - * if arg_type not in type_to_output_cls: - * return used_arg - * output_cls = type_to_output_cls[arg_type] - * if arg_type is tuple: - * inst = super(output_cls, output_cls).__new__(output_cls, used_arg) # type: ignore - * inst = typing.cast(U, inst) - * return inst - * assert issubclass(output_cls, validation.immutabledict) - * inst = super(output_cls, output_cls).__new__(output_cls, used_arg) # type: ignore - * inst = typing.cast(T, inst) - * return inst - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: None, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> None: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Literal[True], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> typing.Literal[True]: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Literal[False], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> typing.Literal[False]: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: bool, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> bool: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: int, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> int: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: float, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> float: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Union[str, datetime.date, datetime.datetime, uuid.UUID], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> str: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: SequenceNotStr[INPUT_TYPES_ALL], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> U: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: U, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> U: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Mapping[str, object], # object needed as value type for typeddict inputs - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> T: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Union[ - * typing.Mapping[str, INPUT_TYPES_ALL], - * T - * ], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> T: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: typing.Union[io.FileIO, io.BufferedReader], - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> FileIO: ... - * - * @typing.overload - * @classmethod - * def validate_base( - * cls, - * arg: bytes, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None - * ) -> bytes: ... - * - * @classmethod - * def validate_base( - * cls, - * arg, - * configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None, - * ): - * """ - * Schema validate_base - * - * Args: - * arg (int/float/str/list/tuple/dict/validation.immutabledict/bool/None): the value - * configuration: contains the schema_configuration.SchemaConfiguration that enables json schema validation keywords - * like minItems, minLength etc - * """ - * if isinstance(arg, (tuple, validation.immutabledict)): - * type_to_output_cls = cls.__get_type_to_output_cls() - * if type_to_output_cls is not None: - * for output_cls in type_to_output_cls.values(): - * if isinstance(arg, output_cls): - * # U + T use case, don't run validations twice - * return arg - * - * from_server = False - * validated_path_to_schemas: typing.Dict[ - * typing.Tuple[typing.Union[str, int], ...], - * typing.Set[typing.Union[str, int, float, bool, None, validation.immutabledict, tuple]] - * ] = {} - * path_to_type: typing.Dict[typing.Tuple[typing.Union[str, int], ...], type] = {} - * cast_arg = cast_to_allowed_types( - * arg, from_server, validated_path_to_schemas, ('args[0]',), path_to_type) - * validation_metadata = validation.ValidationMetadata( - * path_to_item=('args[0]',), - * configuration=configuration or schema_configuration.SchemaConfiguration(), - * validated_path_to_schemas=validation.immutabledict(validated_path_to_schemas) - * ) - * path_to_schemas = cls.__get_path_to_schemas(cast_arg, validation_metadata, path_to_type) - * return cls._get_new_instance_without_conversion( - * cast_arg, - * validation_metadata.path_to_item, - * path_to_schemas, - * ) - * - * @classmethod - * def __get_type_to_output_cls(cls) -> typing.Optional[typing.Mapping[type, type]]: - * type_to_output_cls = getattr(cls(), 'type_to_output_cls', None) - * type_to_output_cls = typing.cast(typing.Optional[typing.Mapping[type, type]], type_to_output_cls) - * return type_to_output_cls - */ \ No newline at end of file +} \ No newline at end of file diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java index f1ad528348d..f2e8d8a37b1 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java @@ -7,6 +7,7 @@ import java.lang.reflect.RecordComponent; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -54,7 +55,7 @@ static PathToSchemasMap _validate( Class baseClass = arg.getClass(); List pathToItem = validationMetadata.pathToItem(); if (!pathToSchemas.containsKey(pathToItem)) { - pathToSchemas.put(validationMetadata.pathToItem(), new HashMap<>()); + pathToSchemas.put(validationMetadata.pathToItem(), new LinkedHashMap<>()); } pathToSchemas.get(pathToItem).put(baseClass, null); pathToSchemas.get(pathToItem).put(schemaCls, null); diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java new file mode 100644 index 00000000000..a18d1f61058 --- /dev/null +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java @@ -0,0 +1,54 @@ +package org.openapijsonschematools.schemas; + +import org.openapijsonschematools.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; + +record UnsetAnyTypeSchema() implements Schema { + public static UnsetAnyTypeSchema withDefaults() { + return new UnsetAnyTypeSchema(); + } + + public static Void validate(Void arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Integer validate(Integer arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Float validate(Float arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Double validate(Double arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(String arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(LocalDate arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static T validate(T arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static U validate(U arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } +} diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java index d5905d10564..96b90e741e5 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java @@ -6,9 +6,8 @@ import org.openapijsonschematools.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -38,7 +37,7 @@ public void testValidateSucceeds() throws InstantiationException, IllegalAccessE validationMetadata ); PathToSchemasMap expectedPathToSchemas = new PathToSchemasMap(); - HashMap, Void> validatedClasses = new HashMap<>(); + LinkedHashMap, Void> validatedClasses = new LinkedHashMap<>(); validatedClasses.put(SomeSchema.class, null); validatedClasses.put(String.class, null); expectedPathToSchemas.put(pathToItem, validatedClasses); diff --git a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java index c0352494b52..12d5d28f2be 100644 --- a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java +++ b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java @@ -261,26 +261,43 @@ protected String testPackagePath() { public void processOpts() { HashMap schemaDocs = new HashMap<>(); additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); + supportingFiles.add(new SupportingFile( + "src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs", + packagePath() + File.separatorChar + "schemas", + "AnyTypeSchema.java")); supportingFiles.add(new SupportingFile( "src/main/java/org/openapitools/schemas/CustomIsoparser.hbs", packagePath() + File.separatorChar + "schemas", "CustomIsoparser.java")); supportingFiles.add(new SupportingFile( - "src/test/java/org/openapitools/schemas/CustomIsoparserTest.hbs", - testPackagePath() + File.separatorChar + "schemas", - "CustomIsoparserTest.java")); + "src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs", + packagePath() + File.separatorChar + "schemas", + "PathToSchemasMap.java")); supportingFiles.add(new SupportingFile( - "src/main/java/org/openapitools/schemas/ValidationMetadata.hbs", + "src/main/java/org/openapitools/schemas/PathToTypeMap.hbs", packagePath() + File.separatorChar + "schemas", - "ValidationMetadata.java")); + "PathToTypeMap.java")); supportingFiles.add(new SupportingFile( - "src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs", + "src/main/java/org/openapitools/schemas/Schema.hbs", packagePath() + File.separatorChar + "schemas", - "PathToSchemasMap.java")); + "Schema.java")); supportingFiles.add(new SupportingFile( "src/main/java/org/openapitools/schemas/SchemaValidator.hbs", packagePath() + File.separatorChar + "schemas", "SchemaValidator.java")); + supportingFiles.add(new SupportingFile( + "src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs", + packagePath() + File.separatorChar + "schemas", + "UnsetAnyTypeSchema.java")); + supportingFiles.add(new SupportingFile( + "src/main/java/org/openapitools/schemas/ValidationMetadata.hbs", + packagePath() + File.separatorChar + "schemas", + "ValidationMetadata.java")); + // tests + supportingFiles.add(new SupportingFile( + "src/test/java/org/openapitools/schemas/CustomIsoparserTest.hbs", + testPackagePath() + File.separatorChar + "schemas", + "CustomIsoparserTest.java")); supportingFiles.add(new SupportingFile( "src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs", testPackagePath() + File.separatorChar + "schemas", @@ -291,11 +308,11 @@ public void processOpts() { "src/main/java/org/openapitools/schemas/validators/KeywordValidator.hbs", packagePath() + File.separatorChar + "schemas" + File.separatorChar + "validators", "KeywordValidator.java")); - // type supportingFiles.add(new SupportingFile( "src/main/java/org/openapitools/schemas/validators/TypeValidator.hbs", packagePath() + File.separatorChar + "schemas" + File.separatorChar + "validators", "TypeValidator.java")); + // tests supportingFiles.add(new SupportingFile( "src/test/java/org/openapitools/schemas/validators/TypeValidatorTest.hbs", testPackagePath() + File.separatorChar + "schemas" + File.separatorChar + "validators", diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs new file mode 100644 index 00000000000..61bdea35147 --- /dev/null +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs @@ -0,0 +1,54 @@ +package {{{packageName}}}.schemas; + +import {{{packageName}}}.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; + +record AnyTypeSchema() implements Schema { + public static AnyTypeSchema withDefaults() { + return new AnyTypeSchema(); + } + + public static Void validate(Void arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Integer validate(Integer arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Float validate(Float arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static Double validate(Double arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(String arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static String validate(LocalDate arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static T validate(T arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } + + public static U validate(U arg, SchemaConfiguration configuration) { + return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + } +} diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs index cc8526fb767..7aa27723b42 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToSchemasMap.hbs @@ -1,8 +1,20 @@ package {{{packageName}}}.schemas; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public class PathToSchemasMap extends HashMap, Map, Void>> { +public class PathToSchemasMap extends LinkedHashMap, LinkedHashMap, Void>> { + + public void update(PathToSchemasMap other) { + for (Map.Entry, LinkedHashMap, Void>> entry: other.entrySet()) { + List pathToItem = entry.getKey(); + LinkedHashMap, Void> otherSchemas = entry.getValue(); + if (containsKey(pathToItem)) { + get(pathToItem).putAll(otherSchemas); + } else { + put(pathToItem, otherSchemas); + } + } + } } \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToTypeMap.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToTypeMap.hbs new file mode 100644 index 00000000000..d16c7f5fe9c --- /dev/null +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/PathToTypeMap.hbs @@ -0,0 +1,8 @@ +package {{{packageName}}}.schemas; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PathToTypeMap extends HashMap, Class> { +} \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs new file mode 100644 index 00000000000..2c7bc8189f0 --- /dev/null +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs @@ -0,0 +1,238 @@ +package {{{packageName}}}.schemas; + +import {{{packageName}}}.configurations.JsonSchemaKeywordFlags; +import {{{packageName}}}.configurations.SchemaConfiguration; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface Schema extends SchemaValidator { + static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { + if (arg == null) { + pathToType.put(pathToItem, Void.class); + return null; + } else if (arg instanceof String) { + pathToType.put(pathToItem, String.class); + return (String) arg; + } else if (arg instanceof Map) { + pathToType.put(pathToItem, Map.class); + LinkedHashMap argFixed = new LinkedHashMap<>(); + for (Map.Entry entry: ((Map) arg).entrySet()) { + String key = (String) entry.getKey(); + Object val = entry.getValue(); + List newPathToItem = new ArrayList<>(pathToItem); + newPathToItem.add(key); + Object fixedVal = castToAllowedTypes(val, newPathToItem, pathToType); + argFixed.put(key, fixedVal); + } + return argFixed; + } else if (arg instanceof Boolean) { + pathToType.put(pathToItem, Boolean.class); + return (Boolean) arg; + } else if (arg instanceof Integer) { + pathToType.put(pathToItem, Integer.class); + return (Integer) arg; + } else if (arg instanceof Float) { + pathToType.put(pathToItem, Float.class); + return (Float) arg; + } else if (arg instanceof Double) { + pathToType.put(pathToItem, Double.class); + return (Double) arg; + } else if (arg instanceof BigDecimal) { + pathToType.put(pathToItem, BigDecimal.class); + return (BigDecimal) arg; + } else if (arg instanceof List) { + pathToType.put(pathToItem, List.class); + List argFixed = new ArrayList<>(); + int i =0; + for (Object item: ((List) arg).toArray()) { + List newPathToItem = new ArrayList<>(pathToItem); + newPathToItem.add(i); + Object fixedVal = castToAllowedTypes(item, newPathToItem, pathToType); + argFixed.add(fixedVal); + i += 1; + } + return argFixed; + } else if (arg instanceof ZonedDateTime) { + pathToType.put(pathToItem, String.class); + return arg.toString(); + } else if (arg instanceof LocalDate) { + pathToType.put(pathToItem, String.class); + return arg.toString(); + } else { + Class argClass = arg.getClass(); + throw new RuntimeException("Invalid type passed in got input="+arg+" type="+argClass); + } + } + + static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { + PathToSchemasMap pathToSchemasMap = new PathToSchemasMap(); + if (validationMetadata.validationRanEarlier(cls)) { + // todo add deeper validated schemas + } else { + try { + PathToSchemasMap otherPathToSchemas = SchemaValidator._validate(cls, arg, validationMetadata); + pathToSchemasMap.update(otherPathToSchemas); + } catch (InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + for (LinkedHashMap, Void> schemas: pathToSchemasMap.values()) { + Class firstSchema = schemas.firstEntry().getKey(); + schemas.clear(); + schemas.put(firstSchema, null); + } + Set> missingPaths = new HashSet<>(pathToType.keySet()); + missingPaths.removeAll(pathToSchemasMap.keySet()); + if (!missingPaths.isEmpty()) { + LinkedHashMap, Void> unsetAnyTypeSchema = new LinkedHashMap<>(); + unsetAnyTypeSchema.put(UnsetAnyTypeSchema.class, null); + for (List pathToItem: missingPaths) { + pathToSchemasMap.put(pathToItem, unsetAnyTypeSchema); + } + } + } + return pathToSchemasMap; + } + + static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + LinkedHashMap properties = new LinkedHashMap<>(); + Map castArg = (Map) arg; + for(Map.Entry entry: castArg.entrySet()) { + String propertyName = entry.getKey(); + List propertyPathToItem = new ArrayList<>(pathToItem); + propertyPathToItem.add(propertyName); + Class propertyClass = (Class) pathToSchemas.get(propertyPathToItem).firstEntry().getKey(); + Object value = entry.getValue(); + Object castValue = getNewInstance(propertyClass, value, propertyPathToItem, pathToSchemas); + properties.put(propertyName, castValue); + } + return properties; + } + + static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + ArrayList items = new ArrayList<>(); + List castItems = (List) arg; + int i = 0; + for (Object item: items) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + Class itemClass = (Class) pathToSchemas.get(itemPathToItem).firstEntry().getKey(); + Object castItem = getNewInstance(itemClass, item, itemPathToItem, pathToSchemas); + items.add(castItem); + i += 1; + } + return items; + } + + static Map, Class> getTypeToOutputClass(Class cls) { + try { + // This must be implemented in Schemas that are generics as a static method + Method method = cls.getMethod("typeToOutputClass"); + Map, Class> typeToOutputClass = (Map, Class>) method.invoke(null); + return typeToOutputClass; + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + return null; + } + } + + static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + Object usedArg; + if (arg instanceof Map) { + usedArg = getProperties(arg, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + usedArg = getItems(arg, pathToItem, pathToSchemas); + } else if (arg instanceof Boolean) { + return (Boolean) arg; + } else { + // str, int, float, FileIO, bytes + return arg; + } + Class argType = arg.getClass(); + Map, Class> typeToOutputClass = getTypeToOutputClass(cls); + if (typeToOutputClass == null) { + return usedArg; + } + Class outputClass = typeToOutputClass.get(argType); + // TODO add class instantiation here + return null; + } + + public static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { + return (Void) validateObjectBase(cls, arg, configuration); + } + + public static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { + return (Boolean) validateObjectBase(cls, arg, configuration); + } + + public static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { + return (Integer) validateObjectBase(cls, arg, configuration); + } + + public static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { + return (Float) validateObjectBase(cls, arg, configuration); + } + + public static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { + return (Double) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { + return (String) validateObjectBase(cls, arg, configuration); + } + + public static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { + return (T) validateObjectBase(cls, arg, configuration); + } + + public static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { + return (U) validateObjectBase(cls, arg, configuration); + } + + // todo add bytes and FileIO + + private static Object validateObjectBase(Class cls, Object arg, SchemaConfiguration configuration) { + Class castCls = (Class) cls; + if (arg instanceof Map || arg instanceof List) { + // todo don't run validation if the instance is one of the class generic types + } + PathToTypeMap pathToType = new PathToTypeMap(); + List pathToItem = new ArrayList<>(); + pathToItem.add("args[0]"); + Object castArg = castToAllowedTypes(arg, pathToItem, pathToType); + SchemaConfiguration usedConfiguration; + if (configuration != null) { + usedConfiguration = configuration; + } else { + usedConfiguration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); + } + PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); + ValidationMetadata validationMetadata = new ValidationMetadata( + pathToItem, + usedConfiguration, + validatedPathToSchemas, + new LinkedHashSet<>() + ); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(castCls, castArg, validationMetadata, pathToType); + return getNewInstance(castCls, castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + +} \ No newline at end of file diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs index 2cacdf30613..076d5cf7bcb 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs @@ -1,12 +1,13 @@ -package org.openapijsonschematools.schemas; +package {{{packageName}}}.schemas; -import org.openapijsonschematools.schemas.validators.KeywordValidator; -import org.openapijsonschematools.schemas.validators.TypeValidator; +import {{{packageName}}}.schemas.validators.KeywordValidator; +import {{{packageName}}}.schemas.validators.TypeValidator; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.RecordComponent; import java.util.HashMap; import java.util.LinkedHashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -54,7 +55,7 @@ public interface SchemaValidator { Class baseClass = arg.getClass(); List pathToItem = validationMetadata.pathToItem(); if (!pathToSchemas.containsKey(pathToItem)) { - pathToSchemas.put(validationMetadata.pathToItem(), new HashMap<>()); + pathToSchemas.put(validationMetadata.pathToItem(), new LinkedHashMap<>()); } pathToSchemas.get(pathToItem).put(baseClass, null); pathToSchemas.get(pathToItem).put(schemaCls, null); diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs new file mode 100644 index 00000000000..ae80a96a5e9 --- /dev/null +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs @@ -0,0 +1,54 @@ +package {{{packageName}}}.schemas; + +import {{{packageName}}}.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; + +record UnsetAnyTypeSchema() implements Schema { + public static UnsetAnyTypeSchema withDefaults() { + return new UnsetAnyTypeSchema(); + } + + public static Void validate(Void arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Integer validate(Integer arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Float validate(Float arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static Double validate(Double arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(String arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static String validate(LocalDate arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static T validate(T arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } + + public static U validate(U arg, SchemaConfiguration configuration) { + return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + } +} diff --git a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs index 876e041689f..2854cb5b775 100644 --- a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs +++ b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs @@ -7,12 +7,12 @@ import {{{packageName}}}.configurations.SchemaConfiguration; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; record SomeSchema(LinkedHashSet> type) implements SchemaValidator { - static SomeSchema withDefaults() { + public static SomeSchema withDefaults() { LinkedHashSet> type = new LinkedHashSet<>(); type.add(String.class); return new SomeSchema(type); @@ -37,7 +37,7 @@ public class SchemaValidatorTest { validationMetadata ); PathToSchemasMap expectedPathToSchemas = new PathToSchemasMap(); - HashMap, Void> validatedClasses = new HashMap<>(); + LinkedHashMap, Void> validatedClasses = new LinkedHashMap<>(); validatedClasses.put(SomeSchema.class, null); validatedClasses.put(String.class, null); expectedPathToSchemas.put(pathToItem, validatedClasses); From 2eefc3c5948e0aa93aa6a941b6e854e619feac01 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 16:16:02 -0800 Subject: [PATCH 07/11] Fixes java warnings, fixes anytypeschema test --- .../schemas/Schema.java | 46 ++++++------- .../schemas/SchemaValidator.java | 15 ++++- .../schemas/AnyTypeSchemaTest.java | 65 +++++++++++++++++++ .../java/org/openapitools/schemas/Schema.hbs | 52 +++++++-------- .../openapitools/schemas/SchemaValidator.hbs | 15 ++++- 5 files changed, 132 insertions(+), 61 deletions(-) create mode 100644 samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index 851bb5e27c7..1ba1d246aa7 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -14,6 +14,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; public interface Schema extends SchemaValidator { @@ -23,7 +24,7 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType return null; } else if (arg instanceof String) { pathToType.put(pathToItem, String.class); - return (String) arg; + return arg; } else if (arg instanceof Map) { pathToType.put(pathToItem, Map.class); LinkedHashMap argFixed = new LinkedHashMap<>(); @@ -38,19 +39,19 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType return argFixed; } else if (arg instanceof Boolean) { pathToType.put(pathToItem, Boolean.class); - return (Boolean) arg; + return arg; } else if (arg instanceof Integer) { pathToType.put(pathToItem, Integer.class); - return (Integer) arg; + return arg; } else if (arg instanceof Float) { pathToType.put(pathToItem, Float.class); - return (Float) arg; + return arg; } else if (arg instanceof Double) { pathToType.put(pathToItem, Double.class); - return (Double) arg; + return arg; } else if (arg instanceof BigDecimal) { pathToType.put(pathToItem, BigDecimal.class); - return (BigDecimal) arg; + return arg; } else if (arg instanceof List) { pathToType.put(pathToItem, List.class); List argFixed = new ArrayList<>(); @@ -123,7 +124,7 @@ static List getItems(Object arg, List pathToItem, PathToSchemasM ArrayList items = new ArrayList<>(); List castItems = (List) arg; int i = 0; - for (Object item: items) { + for (Object item: castItems) { List itemPathToItem = new ArrayList<>(pathToItem); itemPathToItem.add(i); Class itemClass = (Class) pathToSchemas.get(itemPathToItem).entrySet().iterator().next().getKey(); @@ -151,10 +152,8 @@ static Object getNewInstance(Class cls, Object arg, List pathToI usedArg = getProperties(arg, pathToItem, pathToSchemas); } else if (arg instanceof List) { usedArg = getItems(arg, pathToItem, pathToSchemas); - } else if (arg instanceof Boolean) { - return (Boolean) arg; } else { - // str, int, float, FileIO, bytes + // str, int, float, boolean, null, FileIO, bytes return arg; } Class argType = arg.getClass(); @@ -167,43 +166,43 @@ static Object getNewInstance(Class cls, Object arg, List pathToI return null; } - public static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { + static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { return (Void) validateObjectBase(cls, arg, configuration); } - public static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { + static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { return (Boolean) validateObjectBase(cls, arg, configuration); } - public static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { + static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { return (Integer) validateObjectBase(cls, arg, configuration); } - public static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { + static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { return (Float) validateObjectBase(cls, arg, configuration); } - public static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { + static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { return (Double) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { + static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { return (T) validateObjectBase(cls, arg, configuration); } - public static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { + static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { return (U) validateObjectBase(cls, arg, configuration); } @@ -218,12 +217,7 @@ private static Object validateObjectBase(Class cls, Object arg, SchemaConfigu List pathToItem = new ArrayList<>(); pathToItem.add("args[0]"); Object castArg = castToAllowedTypes(arg, pathToItem, pathToType); - SchemaConfiguration usedConfiguration; - if (configuration != null) { - usedConfiguration = configuration; - } else { - usedConfiguration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); - } + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); ValidationMetadata validationMetadata = new ValidationMetadata( pathToItem, diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java index f2e8d8a37b1..f304abdb359 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java @@ -12,7 +12,7 @@ import java.util.Map; public interface SchemaValidator { - static final HashMap keywordToValidator = new HashMap(){{ + HashMap keywordToValidator = new HashMap(){{ put("type", new TypeValidator()); }}; @@ -22,7 +22,7 @@ static PathToSchemasMap _validate( ValidationMetadata validationMetadata ) throws InvocationTargetException, IllegalAccessException { HashMap fieldsToValues = new HashMap<>(); - SchemaValidator schema = null; + SchemaValidator schema; try { schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); } catch (NoSuchMethodException e) { @@ -51,8 +51,17 @@ static PathToSchemasMap _validate( castSchemaCls, validationMetadata ); + if (otherPathToSchemas == null) { + continue; + } + pathToSchemas.update(otherPathToSchemas); + } + Class baseClass; + if (arg == null) { + baseClass = Void.class; + } else { + baseClass = arg.getClass(); } - Class baseClass = arg.getClass(); List pathToItem = validationMetadata.pathToItem(); if (!pathToSchemas.containsKey(pathToItem)) { pathToSchemas.put(validationMetadata.pathToItem(), new LinkedHashMap<>()); diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java new file mode 100644 index 00000000000..18e87df6fdd --- /dev/null +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java @@ -0,0 +1,65 @@ +package org.openapijsonschematools.schemas; + +import org.junit.Assert; +import org.junit.Test; +import org.openapijsonschematools.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +public class AnyTypeSchemaTest { + static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); + + @Test + public void testValidateNull() { + Void validatedValue = AnyTypeSchema.validate((Void) null, configuration); + Assert.assertNull(validatedValue); + } + + @Test + public void testValidateBoolean() { + Boolean trueValue = AnyTypeSchema.validate(Boolean.TRUE, configuration); + Assert.assertEquals(trueValue, Boolean.TRUE); + + Boolean falseValue = AnyTypeSchema.validate(Boolean.FALSE, configuration); + Assert.assertEquals(falseValue, Boolean.FALSE); + } + + @Test + public void testValidateInt() { + Integer validatedValue = AnyTypeSchema.validate(1, configuration); + Assert.assertEquals(validatedValue, Integer.valueOf(1)); + } + + @Test + public void testValidateFloat() { + Float validatedValue = AnyTypeSchema.validate(3.14f, configuration); + Assert.assertEquals(validatedValue, Float.valueOf(3.14f)); + } + + @Test + public void testValidateDouble() { + Double validatedValue = AnyTypeSchema.validate(70.6458763d, configuration); + Assert.assertEquals(validatedValue, Double.valueOf(70.6458763d)); + } + + @Test + public void testValidateString() { + String validatedValue = AnyTypeSchema.validate("a", configuration); + Assert.assertEquals(validatedValue, "a"); + } + + @Test + public void testValidateZonedDateTime() { + String validatedValue = AnyTypeSchema.validate(ZonedDateTime.of(2017, 7, 21, 17, 32, 28, 0, ZoneId.of("Z")), configuration); + Assert.assertEquals(validatedValue, "2017-07-21T17:32:28Z"); + } + + @Test + public void testValidateLocalDate() { + String validatedValue = AnyTypeSchema.validate(LocalDate.of(2017, 7, 21), configuration); + Assert.assertEquals(validatedValue, "2017-07-21"); + } +} diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs index 2c7bc8189f0..111e90cb59c 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs @@ -14,6 +14,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; public interface Schema extends SchemaValidator { @@ -23,7 +24,7 @@ public interface Schema extends SchemaValidator { return null; } else if (arg instanceof String) { pathToType.put(pathToItem, String.class); - return (String) arg; + return arg; } else if (arg instanceof Map) { pathToType.put(pathToItem, Map.class); LinkedHashMap argFixed = new LinkedHashMap<>(); @@ -38,19 +39,19 @@ public interface Schema extends SchemaValidator { return argFixed; } else if (arg instanceof Boolean) { pathToType.put(pathToItem, Boolean.class); - return (Boolean) arg; + return arg; } else if (arg instanceof Integer) { pathToType.put(pathToItem, Integer.class); - return (Integer) arg; + return arg; } else if (arg instanceof Float) { pathToType.put(pathToItem, Float.class); - return (Float) arg; + return arg; } else if (arg instanceof Double) { pathToType.put(pathToItem, Double.class); - return (Double) arg; + return arg; } else if (arg instanceof BigDecimal) { pathToType.put(pathToItem, BigDecimal.class); - return (BigDecimal) arg; + return arg; } else if (arg instanceof List) { pathToType.put(pathToItem, List.class); List argFixed = new ArrayList<>(); @@ -87,7 +88,7 @@ public interface Schema extends SchemaValidator { throw new RuntimeException(e); } for (LinkedHashMap, Void> schemas: pathToSchemasMap.values()) { - Class firstSchema = schemas.firstEntry().getKey(); + Class firstSchema = schemas.entrySet().iterator().next().getKey(); schemas.clear(); schemas.put(firstSchema, null); } @@ -111,7 +112,7 @@ public interface Schema extends SchemaValidator { String propertyName = entry.getKey(); List propertyPathToItem = new ArrayList<>(pathToItem); propertyPathToItem.add(propertyName); - Class propertyClass = (Class) pathToSchemas.get(propertyPathToItem).firstEntry().getKey(); + Class propertyClass = (Class) pathToSchemas.get(propertyPathToItem).entrySet().iterator().next().getKey(); Object value = entry.getValue(); Object castValue = getNewInstance(propertyClass, value, propertyPathToItem, pathToSchemas); properties.put(propertyName, castValue); @@ -123,10 +124,10 @@ public interface Schema extends SchemaValidator { ArrayList items = new ArrayList<>(); List castItems = (List) arg; int i = 0; - for (Object item: items) { + for (Object item: castItems) { List itemPathToItem = new ArrayList<>(pathToItem); itemPathToItem.add(i); - Class itemClass = (Class) pathToSchemas.get(itemPathToItem).firstEntry().getKey(); + Class itemClass = (Class) pathToSchemas.get(itemPathToItem).entrySet().iterator().next().getKey(); Object castItem = getNewInstance(itemClass, item, itemPathToItem, pathToSchemas); items.add(castItem); i += 1; @@ -151,10 +152,8 @@ public interface Schema extends SchemaValidator { usedArg = getProperties(arg, pathToItem, pathToSchemas); } else if (arg instanceof List) { usedArg = getItems(arg, pathToItem, pathToSchemas); - } else if (arg instanceof Boolean) { - return (Boolean) arg; } else { - // str, int, float, FileIO, bytes + // str, int, float, boolean, null, FileIO, bytes return arg; } Class argType = arg.getClass(); @@ -167,43 +166,43 @@ public interface Schema extends SchemaValidator { return null; } - public static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { + static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { return (Void) validateObjectBase(cls, arg, configuration); } - public static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { + static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { return (Boolean) validateObjectBase(cls, arg, configuration); } - public static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { + static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { return (Integer) validateObjectBase(cls, arg, configuration); } - public static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { + static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { return (Float) validateObjectBase(cls, arg, configuration); } - public static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { + static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { return (Double) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { + static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { return (String) validateObjectBase(cls, arg, configuration); } - public static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { + static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { return (T) validateObjectBase(cls, arg, configuration); } - public static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { + static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { return (U) validateObjectBase(cls, arg, configuration); } @@ -218,12 +217,7 @@ public interface Schema extends SchemaValidator { List pathToItem = new ArrayList<>(); pathToItem.add("args[0]"); Object castArg = castToAllowedTypes(arg, pathToItem, pathToType); - SchemaConfiguration usedConfiguration; - if (configuration != null) { - usedConfiguration = configuration; - } else { - usedConfiguration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); - } + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); PathToSchemasMap validatedPathToSchemas = new PathToSchemasMap(); ValidationMetadata validationMetadata = new ValidationMetadata( pathToItem, diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs index 076d5cf7bcb..1f2a3f8a476 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs @@ -12,7 +12,7 @@ import java.util.List; import java.util.Map; public interface SchemaValidator { - static final HashMap keywordToValidator = new HashMap()\{{ + HashMap keywordToValidator = new HashMap()\{{ put("type", new TypeValidator()); }}; @@ -22,7 +22,7 @@ public interface SchemaValidator { ValidationMetadata validationMetadata ) throws InvocationTargetException, IllegalAccessException { HashMap fieldsToValues = new HashMap<>(); - SchemaValidator schema = null; + SchemaValidator schema; try { schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); } catch (NoSuchMethodException e) { @@ -51,8 +51,17 @@ public interface SchemaValidator { castSchemaCls, validationMetadata ); + if (otherPathToSchemas == null) { + continue; + } + pathToSchemas.update(otherPathToSchemas); + } + Class baseClass; + if (arg == null) { + baseClass = Void.class; + } else { + baseClass = arg.getClass(); } - Class baseClass = arg.getClass(); List pathToItem = validationMetadata.pathToItem(); if (!pathToSchemas.containsKey(pathToItem)) { pathToSchemas.put(validationMetadata.pathToItem(), new LinkedHashMap<>()); From 9b07a7d88638e61f0d03a6028f8c98784af90f0c Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 16:32:25 -0800 Subject: [PATCH 08/11] Adds test of map and list validation --- .../schemas/AnyTypeSchemaTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java index 18e87df6fdd..b618cc17421 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java @@ -8,6 +8,10 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; public class AnyTypeSchemaTest { static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); @@ -62,4 +66,24 @@ public void testValidateLocalDate() { String validatedValue = AnyTypeSchema.validate(LocalDate.of(2017, 7, 21), configuration); Assert.assertEquals(validatedValue, "2017-07-21"); } + + @Test + public void testValidateMap() { + LinkedHashMap inMap = new LinkedHashMap<>(); + inMap.put("today", LocalDate.of(2017, 7, 21)); + LinkedHashMap validatedValue = AnyTypeSchema.validate(inMap, configuration); + LinkedHashMap outMap = new LinkedHashMap<>(); + outMap.put("today", "2017-07-21"); + Assert.assertEquals(validatedValue, outMap); + } + + @Test + public void testValidateList() { + ArrayList inList = new ArrayList<>(); + inList.add(LocalDate.of(2017, 7, 21)); + ArrayList validatedValue = AnyTypeSchema.validate(inList, configuration); + ArrayList outList = new ArrayList<>(); + outList.add( "2017-07-21"); + Assert.assertEquals(validatedValue, outList); + } } From fc982553825373116846c3f2fec7663b49ce22b7 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 16:44:39 -0800 Subject: [PATCH 09/11] Removes unneeded static keywords from UnsetAnyTypeSchema --- .../petstore/java/.openapi-generator/FILES | 1 + .../schemas/UnsetAnyTypeSchema.java | 22 ++--- .../schemas/AnyTypeSchemaTest.java | 2 - .../generators/JavaClientGenerator.java | 4 + .../schemas/UnsetAnyTypeSchema.hbs | 22 ++--- .../schemas/AnyTypeSchemaTest.hbs | 87 +++++++++++++++++++ 6 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 src/main/resources/java/src/test/java/org/openapitools/schemas/AnyTypeSchemaTest.hbs diff --git a/samples/client/petstore/java/.openapi-generator/FILES b/samples/client/petstore/java/.openapi-generator/FILES index b4ec78422d8..853d8eed662 100644 --- a/samples/client/petstore/java/.openapi-generator/FILES +++ b/samples/client/petstore/java/.openapi-generator/FILES @@ -13,6 +13,7 @@ src/main/java/org/openapijsonschematools/schemas/ValidationMetadata.java src/main/java/org/openapijsonschematools/schemas/validators/KeywordValidator.java src/main/java/org/openapijsonschematools/schemas/validators/TypeValidator.java src/test/java/org/openapijsonschematools/configurations/JsonSchemaKeywordFlagsTest.java +src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java src/test/java/org/openapijsonschematools/schemas/CustomIsoparserTest.java src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java src/test/java/org/openapijsonschematools/schemas/validators/TypeValidatorTest.java diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java index a18d1f61058..eee0f6a8753 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java @@ -8,47 +8,47 @@ import java.util.Map; record UnsetAnyTypeSchema() implements Schema { - public static UnsetAnyTypeSchema withDefaults() { + static UnsetAnyTypeSchema withDefaults() { return new UnsetAnyTypeSchema(); } - public static Void validate(Void arg, SchemaConfiguration configuration) { + static Void validate(Void arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + static Boolean validate(Boolean arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Integer validate(Integer arg, SchemaConfiguration configuration) { + static Integer validate(Integer arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Float validate(Float arg, SchemaConfiguration configuration) { + static Float validate(Float arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Double validate(Double arg, SchemaConfiguration configuration) { + static Double validate(Double arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(String arg, SchemaConfiguration configuration) { + static String validate(String arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(LocalDate arg, SchemaConfiguration configuration) { + static String validate(LocalDate arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static T validate(T arg, SchemaConfiguration configuration) { + static T validate(T arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static U validate(U arg, SchemaConfiguration configuration) { + static U validate(U arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } } diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java index b618cc17421..57333589db3 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/AnyTypeSchemaTest.java @@ -9,9 +9,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.Map; public class AnyTypeSchemaTest { static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); diff --git a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java index 12d5d28f2be..1c38d25ef51 100644 --- a/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java +++ b/src/main/java/org/openapijsonschematools/codegen/generators/JavaClientGenerator.java @@ -294,6 +294,10 @@ public void processOpts() { packagePath() + File.separatorChar + "schemas", "ValidationMetadata.java")); // tests + supportingFiles.add(new SupportingFile( + "src/test/java/org/openapitools/schemas/AnyTypeSchemaTest.hbs", + testPackagePath() + File.separatorChar + "schemas", + "AnyTypeSchemaTest.java")); supportingFiles.add(new SupportingFile( "src/test/java/org/openapitools/schemas/CustomIsoparserTest.hbs", testPackagePath() + File.separatorChar + "schemas", diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs index ae80a96a5e9..742bc5919a3 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs @@ -8,47 +8,47 @@ import java.util.List; import java.util.Map; record UnsetAnyTypeSchema() implements Schema { - public static UnsetAnyTypeSchema withDefaults() { + static UnsetAnyTypeSchema withDefaults() { return new UnsetAnyTypeSchema(); } - public static Void validate(Void arg, SchemaConfiguration configuration) { + static Void validate(Void arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { + static Boolean validate(Boolean arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Integer validate(Integer arg, SchemaConfiguration configuration) { + static Integer validate(Integer arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Float validate(Float arg, SchemaConfiguration configuration) { + static Float validate(Float arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static Double validate(Double arg, SchemaConfiguration configuration) { + static Double validate(Double arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(String arg, SchemaConfiguration configuration) { + static String validate(String arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { + static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static String validate(LocalDate arg, SchemaConfiguration configuration) { + static String validate(LocalDate arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static T validate(T arg, SchemaConfiguration configuration) { + static T validate(T arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } - public static U validate(U arg, SchemaConfiguration configuration) { + static U validate(U arg, SchemaConfiguration configuration) { return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); } } diff --git a/src/main/resources/java/src/test/java/org/openapitools/schemas/AnyTypeSchemaTest.hbs b/src/main/resources/java/src/test/java/org/openapitools/schemas/AnyTypeSchemaTest.hbs new file mode 100644 index 00000000000..43dfa422668 --- /dev/null +++ b/src/main/resources/java/src/test/java/org/openapitools/schemas/AnyTypeSchemaTest.hbs @@ -0,0 +1,87 @@ +package {{{packageName}}}.schemas; + +import org.junit.Assert; +import org.junit.Test; +import {{{packageName}}}.configurations.JsonSchemaKeywordFlags; +import {{{packageName}}}.configurations.SchemaConfiguration; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.LinkedHashMap; + +public class AnyTypeSchemaTest { + static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); + + @Test + public void testValidateNull() { + Void validatedValue = AnyTypeSchema.validate((Void) null, configuration); + Assert.assertNull(validatedValue); + } + + @Test + public void testValidateBoolean() { + Boolean trueValue = AnyTypeSchema.validate(Boolean.TRUE, configuration); + Assert.assertEquals(trueValue, Boolean.TRUE); + + Boolean falseValue = AnyTypeSchema.validate(Boolean.FALSE, configuration); + Assert.assertEquals(falseValue, Boolean.FALSE); + } + + @Test + public void testValidateInt() { + Integer validatedValue = AnyTypeSchema.validate(1, configuration); + Assert.assertEquals(validatedValue, Integer.valueOf(1)); + } + + @Test + public void testValidateFloat() { + Float validatedValue = AnyTypeSchema.validate(3.14f, configuration); + Assert.assertEquals(validatedValue, Float.valueOf(3.14f)); + } + + @Test + public void testValidateDouble() { + Double validatedValue = AnyTypeSchema.validate(70.6458763d, configuration); + Assert.assertEquals(validatedValue, Double.valueOf(70.6458763d)); + } + + @Test + public void testValidateString() { + String validatedValue = AnyTypeSchema.validate("a", configuration); + Assert.assertEquals(validatedValue, "a"); + } + + @Test + public void testValidateZonedDateTime() { + String validatedValue = AnyTypeSchema.validate(ZonedDateTime.of(2017, 7, 21, 17, 32, 28, 0, ZoneId.of("Z")), configuration); + Assert.assertEquals(validatedValue, "2017-07-21T17:32:28Z"); + } + + @Test + public void testValidateLocalDate() { + String validatedValue = AnyTypeSchema.validate(LocalDate.of(2017, 7, 21), configuration); + Assert.assertEquals(validatedValue, "2017-07-21"); + } + + @Test + public void testValidateMap() { + LinkedHashMap inMap = new LinkedHashMap<>(); + inMap.put("today", LocalDate.of(2017, 7, 21)); + LinkedHashMap validatedValue = AnyTypeSchema.validate(inMap, configuration); + LinkedHashMap outMap = new LinkedHashMap<>(); + outMap.put("today", "2017-07-21"); + Assert.assertEquals(validatedValue, outMap); + } + + @Test + public void testValidateList() { + ArrayList inList = new ArrayList<>(); + inList.add(LocalDate.of(2017, 7, 21)); + ArrayList validatedValue = AnyTypeSchema.validate(inList, configuration); + ArrayList outList = new ArrayList<>(); + outList.add( "2017-07-21"); + Assert.assertEquals(validatedValue, outList); + } +} From a4360c0922e540087e065dae5b8dc4c2878c8ae4 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 16:51:43 -0800 Subject: [PATCH 10/11] Makes private methods private --- .../org/openapijsonschematools/schemas/Schema.java | 12 ++++++------ .../main/java/org/openapitools/schemas/Schema.hbs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index 1ba1d246aa7..0a6b1a182bd 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -18,7 +18,7 @@ import java.util.Set; public interface Schema extends SchemaValidator { - static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { + private static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { if (arg == null) { pathToType.put(pathToItem, Void.class); return null; @@ -76,7 +76,7 @@ static Object castToAllowedTypes(Object arg, List pathToItem, PathToType } } - static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { + private static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { PathToSchemasMap pathToSchemasMap = new PathToSchemasMap(); if (validationMetadata.validationRanEarlier(cls)) { // todo add deeper validated schemas @@ -105,7 +105,7 @@ static PathToSchemasMap getPathToSchemas(Class cls, Object arg, Validati return pathToSchemasMap; } - static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { LinkedHashMap properties = new LinkedHashMap<>(); Map castArg = (Map) arg; for(Map.Entry entry: castArg.entrySet()) { @@ -120,7 +120,7 @@ static LinkedHashMap getProperties(Object arg, List path return properties; } - static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { ArrayList items = new ArrayList<>(); List castItems = (List) arg; int i = 0; @@ -135,7 +135,7 @@ static List getItems(Object arg, List pathToItem, PathToSchemasM return items; } - static Map, Class> getTypeToOutputClass(Class cls) { + private static Map, Class> getTypeToOutputClass(Class cls) { try { // This must be implemented in Schemas that are generics as a static method Method method = cls.getMethod("typeToOutputClass"); @@ -146,7 +146,7 @@ static Map, Class> getTypeToOutputClass(Class cls) { } } - static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { Object usedArg; if (arg instanceof Map) { usedArg = getProperties(arg, pathToItem, pathToSchemas); diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs index 111e90cb59c..197f484afd5 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs @@ -18,7 +18,7 @@ import java.util.Objects; import java.util.Set; public interface Schema extends SchemaValidator { - static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { + private static Object castToAllowedTypes(Object arg, List pathToItem, PathToTypeMap pathToType) { if (arg == null) { pathToType.put(pathToItem, Void.class); return null; @@ -76,7 +76,7 @@ public interface Schema extends SchemaValidator { } } - static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { + private static PathToSchemasMap getPathToSchemas(Class cls, Object arg, ValidationMetadata validationMetadata, PathToTypeMap pathToType) { PathToSchemasMap pathToSchemasMap = new PathToSchemasMap(); if (validationMetadata.validationRanEarlier(cls)) { // todo add deeper validated schemas @@ -105,7 +105,7 @@ public interface Schema extends SchemaValidator { return pathToSchemasMap; } - static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static LinkedHashMap getProperties(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { LinkedHashMap properties = new LinkedHashMap<>(); Map castArg = (Map) arg; for(Map.Entry entry: castArg.entrySet()) { @@ -120,7 +120,7 @@ public interface Schema extends SchemaValidator { return properties; } - static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static List getItems(Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { ArrayList items = new ArrayList<>(); List castItems = (List) arg; int i = 0; @@ -135,7 +135,7 @@ public interface Schema extends SchemaValidator { return items; } - static Map, Class> getTypeToOutputClass(Class cls) { + private static Map, Class> getTypeToOutputClass(Class cls) { try { // This must be implemented in Schemas that are generics as a static method Method method = cls.getMethod("typeToOutputClass"); @@ -146,7 +146,7 @@ public interface Schema extends SchemaValidator { } } - static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + private static Object getNewInstance(Class cls, Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { Object usedArg; if (arg instanceof Map) { usedArg = getProperties(arg, pathToItem, pathToSchemas); From d7a2e1448194859be6e1651e42e64f47ea7d8a0b Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 6 Nov 2023 17:14:44 -0800 Subject: [PATCH 11/11] Renames methods validate, romoves exception throwing --- .../schemas/AnyTypeSchema.java | 20 ++++---- .../schemas/Schema.java | 50 +++++++++---------- .../schemas/SchemaValidator.java | 14 ++++-- .../schemas/UnsetAnyTypeSchema.java | 20 ++++---- .../schemas/SchemaValidatorTest.java | 4 +- .../openapitools/schemas/AnyTypeSchema.hbs | 20 ++++---- .../java/org/openapitools/schemas/Schema.hbs | 50 +++++++++---------- .../openapitools/schemas/SchemaValidator.hbs | 14 ++++-- .../schemas/UnsetAnyTypeSchema.hbs | 20 ++++---- .../schemas/SchemaValidatorTest.hbs | 4 +- 10 files changed, 108 insertions(+), 108 deletions(-) diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java index f98510dc77c..500739c8cb4 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/AnyTypeSchema.java @@ -13,42 +13,42 @@ public static AnyTypeSchema withDefaults() { } public static Void validate(Void arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Integer validate(Integer arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Float validate(Float arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Double validate(Double arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(String arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(LocalDate arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static T validate(T arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static U validate(U arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } } diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java index 0a6b1a182bd..749e82074aa 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/Schema.java @@ -81,12 +81,8 @@ private static PathToSchemasMap getPathToSchemas(Class cls, Object arg, if (validationMetadata.validationRanEarlier(cls)) { // todo add deeper validated schemas } else { - try { - PathToSchemasMap otherPathToSchemas = SchemaValidator._validate(cls, arg, validationMetadata); - pathToSchemasMap.update(otherPathToSchemas); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } + PathToSchemasMap otherPathToSchemas = SchemaValidator.validate(cls, arg, validationMetadata); + pathToSchemasMap.update(otherPathToSchemas); for (LinkedHashMap, Void> schemas: pathToSchemasMap.values()) { Class firstSchema = schemas.entrySet().iterator().next().getKey(); schemas.clear(); @@ -166,49 +162,49 @@ private static Object getNewInstance(Class cls, Object arg, List return null; } - static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { - return (Void) validateObjectBase(cls, arg, configuration); + static Void validate(Class cls, Void arg, SchemaConfiguration configuration) { + return (Void) validateObject(cls, arg, configuration); } - static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { - return (Boolean) validateObjectBase(cls, arg, configuration); + static Boolean validate(Class cls, Boolean arg, SchemaConfiguration configuration) { + return (Boolean) validateObject(cls, arg, configuration); } - static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { - return (Integer) validateObjectBase(cls, arg, configuration); + static Integer validate(Class cls, Integer arg, SchemaConfiguration configuration) { + return (Integer) validateObject(cls, arg, configuration); } - static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { - return (Float) validateObjectBase(cls, arg, configuration); + static Float validate(Class cls, Float arg, SchemaConfiguration configuration) { + return (Float) validateObject(cls, arg, configuration); } - static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { - return (Double) validateObjectBase(cls, arg, configuration); + static Double validate(Class cls, Double arg, SchemaConfiguration configuration) { + return (Double) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, String arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, LocalDate arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { - return (T) validateObjectBase(cls, arg, configuration); + static T validate(Class cls, T arg, SchemaConfiguration configuration) { + return (T) validateObject(cls, arg, configuration); } - static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { - return (U) validateObjectBase(cls, arg, configuration); + static U validate(Class cls, U arg, SchemaConfiguration configuration) { + return (U) validateObject(cls, arg, configuration); } // todo add bytes and FileIO - private static Object validateObjectBase(Class cls, Object arg, SchemaConfiguration configuration) { + private static Object validateObject(Class cls, Object arg, SchemaConfiguration configuration) { Class castCls = (Class) cls; if (arg instanceof Map || arg instanceof List) { // todo don't run validation if the instance is one of the class generic types diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java index f304abdb359..38553c8afcb 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/SchemaValidator.java @@ -16,16 +16,16 @@ public interface SchemaValidator { put("type", new TypeValidator()); }}; - static PathToSchemasMap _validate( + static PathToSchemasMap validate( Class schemaCls, Object arg, ValidationMetadata validationMetadata - ) throws InvocationTargetException, IllegalAccessException { + ) { HashMap fieldsToValues = new HashMap<>(); SchemaValidator schema; try { schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); - } catch (NoSuchMethodException e) { + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); } LinkedHashSet disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords(); @@ -35,8 +35,12 @@ static PathToSchemasMap _validate( if (disabledKeywords.contains(fieldName)) { continue; } - Object value = recordComponent.getAccessor().invoke(schema); - fieldsToValues.put(fieldName, value); + try { + Object value = recordComponent.getAccessor().invoke(schema); + fieldsToValues.put(fieldName, value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } } PathToSchemasMap pathToSchemas = new PathToSchemasMap(); Class castSchemaCls = (Class) schemaCls; diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java index eee0f6a8753..f5120344836 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/schemas/UnsetAnyTypeSchema.java @@ -13,42 +13,42 @@ static UnsetAnyTypeSchema withDefaults() { } static Void validate(Void arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Boolean validate(Boolean arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Integer validate(Integer arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Float validate(Float arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Double validate(Double arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(String arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(LocalDate arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static T validate(T arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static U validate(U arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } } diff --git a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java index 96b90e741e5..6e29f940ca4 100644 --- a/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java +++ b/samples/client/petstore/java/src/test/java/org/openapijsonschematools/schemas/SchemaValidatorTest.java @@ -22,7 +22,7 @@ public static SomeSchema withDefaults() { public class SchemaValidatorTest { @Test - public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + public void testValidateSucceeds() { List pathToItem = new ArrayList<>(); pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( @@ -31,7 +31,7 @@ public void testValidateSucceeds() throws InstantiationException, IllegalAccessE new PathToSchemasMap(), new LinkedHashSet<>() ); - PathToSchemasMap pathToSchemas = SchemaValidator._validate( + PathToSchemasMap pathToSchemas = SchemaValidator.validate( SomeSchema.class, "hi", validationMetadata diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs index 61bdea35147..e328a03b7fb 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/AnyTypeSchema.hbs @@ -13,42 +13,42 @@ record AnyTypeSchema() implements Schema { } public static Void validate(Void arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Boolean validate(Boolean arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Integer validate(Integer arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Float validate(Float arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static Double validate(Double arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(String arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static String validate(LocalDate arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static T validate(T arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } public static U validate(U arg, SchemaConfiguration configuration) { - return Schema.validateBase(AnyTypeSchema.class, arg, configuration); + return Schema.validate(AnyTypeSchema.class, arg, configuration); } } diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs index 197f484afd5..f37ba5a2fb2 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/Schema.hbs @@ -81,12 +81,8 @@ public interface Schema extends SchemaValidator { if (validationMetadata.validationRanEarlier(cls)) { // todo add deeper validated schemas } else { - try { - PathToSchemasMap otherPathToSchemas = SchemaValidator._validate(cls, arg, validationMetadata); - pathToSchemasMap.update(otherPathToSchemas); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new RuntimeException(e); - } + PathToSchemasMap otherPathToSchemas = SchemaValidator.validate(cls, arg, validationMetadata); + pathToSchemasMap.update(otherPathToSchemas); for (LinkedHashMap, Void> schemas: pathToSchemasMap.values()) { Class firstSchema = schemas.entrySet().iterator().next().getKey(); schemas.clear(); @@ -166,49 +162,49 @@ public interface Schema extends SchemaValidator { return null; } - static Void validateBase(Class cls, Void arg, SchemaConfiguration configuration) { - return (Void) validateObjectBase(cls, arg, configuration); + static Void validate(Class cls, Void arg, SchemaConfiguration configuration) { + return (Void) validateObject(cls, arg, configuration); } - static Boolean validateBase(Class cls, Boolean arg, SchemaConfiguration configuration) { - return (Boolean) validateObjectBase(cls, arg, configuration); + static Boolean validate(Class cls, Boolean arg, SchemaConfiguration configuration) { + return (Boolean) validateObject(cls, arg, configuration); } - static Integer validateBase(Class cls, Integer arg, SchemaConfiguration configuration) { - return (Integer) validateObjectBase(cls, arg, configuration); + static Integer validate(Class cls, Integer arg, SchemaConfiguration configuration) { + return (Integer) validateObject(cls, arg, configuration); } - static Float validateBase(Class cls, Float arg, SchemaConfiguration configuration) { - return (Float) validateObjectBase(cls, arg, configuration); + static Float validate(Class cls, Float arg, SchemaConfiguration configuration) { + return (Float) validateObject(cls, arg, configuration); } - static Double validateBase(Class cls, Double arg, SchemaConfiguration configuration) { - return (Double) validateObjectBase(cls, arg, configuration); + static Double validate(Class cls, Double arg, SchemaConfiguration configuration) { + return (Double) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, String arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, String arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, ZonedDateTime arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static String validateBase(Class cls, LocalDate arg, SchemaConfiguration configuration) { - return (String) validateObjectBase(cls, arg, configuration); + static String validate(Class cls, LocalDate arg, SchemaConfiguration configuration) { + return (String) validateObject(cls, arg, configuration); } - static T validateBase(Class cls, T arg, SchemaConfiguration configuration) { - return (T) validateObjectBase(cls, arg, configuration); + static T validate(Class cls, T arg, SchemaConfiguration configuration) { + return (T) validateObject(cls, arg, configuration); } - static U validateBase(Class cls, U arg, SchemaConfiguration configuration) { - return (U) validateObjectBase(cls, arg, configuration); + static U validate(Class cls, U arg, SchemaConfiguration configuration) { + return (U) validateObject(cls, arg, configuration); } // todo add bytes and FileIO - private static Object validateObjectBase(Class cls, Object arg, SchemaConfiguration configuration) { + private static Object validateObject(Class cls, Object arg, SchemaConfiguration configuration) { Class castCls = (Class) cls; if (arg instanceof Map || arg instanceof List) { // todo don't run validation if the instance is one of the class generic types diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs index 1f2a3f8a476..0a8e7e3e484 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/SchemaValidator.hbs @@ -16,16 +16,16 @@ public interface SchemaValidator { put("type", new TypeValidator()); }}; - static PathToSchemasMap _validate( + static PathToSchemasMap validate( Class schemaCls, Object arg, ValidationMetadata validationMetadata - ) throws InvocationTargetException, IllegalAccessException { + ) { HashMap fieldsToValues = new HashMap<>(); SchemaValidator schema; try { schema = (SchemaValidator) schemaCls.getMethod("withDefaults").invoke(null); - } catch (NoSuchMethodException e) { + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); } LinkedHashSet disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords(); @@ -35,8 +35,12 @@ public interface SchemaValidator { if (disabledKeywords.contains(fieldName)) { continue; } - Object value = recordComponent.getAccessor().invoke(schema); - fieldsToValues.put(fieldName, value); + try { + Object value = recordComponent.getAccessor().invoke(schema); + fieldsToValues.put(fieldName, value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } } PathToSchemasMap pathToSchemas = new PathToSchemasMap(); Class castSchemaCls = (Class) schemaCls; diff --git a/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs index 742bc5919a3..284c888645d 100644 --- a/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs +++ b/src/main/resources/java/src/main/java/org/openapitools/schemas/UnsetAnyTypeSchema.hbs @@ -13,42 +13,42 @@ record UnsetAnyTypeSchema() implements Schema { } static Void validate(Void arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Boolean validate(Boolean arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Integer validate(Integer arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Float validate(Float arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static Double validate(Double arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(String arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(ZonedDateTime arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static String validate(LocalDate arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static T validate(T arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } static U validate(U arg, SchemaConfiguration configuration) { - return Schema.validateBase(UnsetAnyTypeSchema.class, arg, configuration); + return Schema.validate(UnsetAnyTypeSchema.class, arg, configuration); } } diff --git a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs index 2854cb5b775..7df95828781 100644 --- a/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs +++ b/src/main/resources/java/src/test/java/org/openapitools/schemas/SchemaValidatorTest.hbs @@ -22,7 +22,7 @@ record SomeSchema(LinkedHashSet> type) implements SchemaValidator { public class SchemaValidatorTest { @Test - public void testValidateSucceeds() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + public void testValidateSucceeds() { List pathToItem = new ArrayList<>(); pathToItem.add("args[0"); ValidationMetadata validationMetadata = new ValidationMetadata( @@ -31,7 +31,7 @@ public class SchemaValidatorTest { new PathToSchemasMap(), new LinkedHashSet<>() ); - PathToSchemasMap pathToSchemas = SchemaValidator._validate( + PathToSchemasMap pathToSchemas = SchemaValidator.validate( SomeSchema.class, "hi", validationMetadata