Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

Feat adds java schema configuration #271

Merged
merged 8 commits into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generators/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ title: Documentation for the java generator
| generator stability | EXPERIMENTAL | |
| generator type | CLIENT | |
| generator language | Java | |
| generator language version | 17 | |
| generator default templating engine | handlebars | |
| helpTxt | Generates a Java client library (HTTP lib: Jersey (1.x, 2.x), Retrofit (2.x), OpenFeign (10.x) and more. | |

Expand Down
9 changes: 9 additions & 0 deletions samples/client/petstore/java/.openapi-generator/FILES
Original file line number Diff line number Diff line change
@@ -1,4 +1,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/CustomIsoparser.java
src/main/java/org/openapijsonschematools/schemas/PathToSchemasMap.java
src/main/java/org/openapijsonschematools/schemas/SchemaValidator.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
src/test/java/org/openapijsonschematools/configurations/JsonSchemaKeywordFlagsTest.java
src/test/java/org/openapijsonschematools/schemas/CustomIsoparserTest.java
src/test/java/org/openapijsonschematools/schemas/validators/TypeValidatorTest.java
3 changes: 1 addition & 2 deletions samples/client/petstore/java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ This Java package is automatically generated by the [OpenAPI JSON Schema Generat

- API version: 1.0.0
- Package version:

- Build package: JavaClientGenerator


## Requirements

Python
Java 17

## Migration Guides
- [3.0.0 Migration Guide](migration_3_0_0.md)
Expand Down
3 changes: 1 addition & 2 deletions samples/client/petstore/java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<fork>true</fork>
<meminitial>128m</meminitial>
<maxmem>512m</maxmem>
Expand Down Expand Up @@ -281,6 +279,7 @@
</dependency>
</dependencies>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<swagger-annotations-version>1.6.3</swagger-annotations-version>
<jersey-version>1.19.4</jersey-version>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package org.openapijsonschematools.configurations;

import java.util.LinkedHashSet;

public record JsonSchemaKeywordFlags(
boolean additionalProperties,
boolean allOf,
boolean anyOf,
boolean const_,
boolean contains,
boolean dependentRequired,
boolean dependentSchemas,
boolean discriminator,
boolean else_,
boolean enum_,
boolean exclusiveMaximum,
boolean exclusiveMinimum,
boolean format,
boolean if_,
boolean maximum,
boolean minimum,
boolean items,
boolean maxContains,
boolean maxItems,
boolean maxLength,
boolean maxProperties,
boolean minContains,
boolean minItems,
boolean minLength,
boolean minProperties,
boolean multipleOf,
boolean not,
boolean oneOf,
boolean pattern,
boolean patternProperties,
boolean prefixItems,
boolean properties,
boolean propertyNames,
boolean required,
boolean then,
boolean type,
boolean uniqueItems,
boolean unevaluatedItems,
boolean unevaluatedProperties
) {

public static JsonSchemaKeywordFlags ofNone() {
return new JsonSchemaKeywordFlags(
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false
);
}

public LinkedHashSet<String> getKeywords() {
LinkedHashSet<String> enabledKeywords = new LinkedHashSet<>();
if (additionalProperties) { enabledKeywords.add("additionalProperties"); }
if (allOf) { enabledKeywords.add("allOf"); }
if (anyOf) { enabledKeywords.add("anyOf"); }
if (const_) { enabledKeywords.add("const_"); }
if (contains) { enabledKeywords.add("contains"); }
if (dependentRequired) { enabledKeywords.add("dependentRequired"); }
if (dependentSchemas) { enabledKeywords.add("dependentSchemas"); }
if (discriminator) { enabledKeywords.add("discriminator"); }
if (else_) { enabledKeywords.add("else_"); }
if (enum_) { enabledKeywords.add("enum_"); }
if (exclusiveMaximum) { enabledKeywords.add("exclusiveMaximum"); }
if (exclusiveMinimum) { enabledKeywords.add("exclusiveMinimum"); }
if (format) { enabledKeywords.add("format"); }
if (if_) { enabledKeywords.add("if_"); }
if (maximum) { enabledKeywords.add("maximum"); }
if (minimum) { enabledKeywords.add("minimum"); }
if (items) { enabledKeywords.add("items"); }
if (maxContains) { enabledKeywords.add("maxContains"); }
if (maxItems) { enabledKeywords.add("maxItems"); }
if (maxLength) { enabledKeywords.add("maxLength"); }
if (maxProperties) { enabledKeywords.add("maxProperties"); }
if (minContains) { enabledKeywords.add("minContains"); }
if (minItems) { enabledKeywords.add("minItems"); }
if (minLength) { enabledKeywords.add("minLength"); }
if (minProperties) { enabledKeywords.add("minProperties"); }
if (multipleOf) { enabledKeywords.add("multipleOf"); }
if (not) { enabledKeywords.add("not"); }
if (oneOf) { enabledKeywords.add("oneOf"); }
if (pattern) { enabledKeywords.add("pattern"); }
if (patternProperties) { enabledKeywords.add("patternProperties"); }
if (prefixItems) { enabledKeywords.add("prefixItems"); }
if (properties) { enabledKeywords.add("properties"); }
if (propertyNames) { enabledKeywords.add("propertyNames"); }
if (required) { enabledKeywords.add("required"); }
if (then) { enabledKeywords.add("then"); }
if (type) { enabledKeywords.add("type"); }
if (uniqueItems) { enabledKeywords.add("uniqueItems"); }
if (unevaluatedItems) { enabledKeywords.add("unevaluatedItems"); }
if (unevaluatedProperties) { enabledKeywords.add("unevaluatedProperties"); }
return enabledKeywords;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.openapijsonschematools.configurations;

public record SchemaConfiguration(JsonSchemaKeywordFlags disabledKeywordFlags) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.openapijsonschematools.schemas;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PathToSchemasMap extends HashMap<List<Object>, Map<Class<?>, Void>> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.openapijsonschematools.schemas;

import org.openapijsonschematools.schemas.validators.KeywordValidator;
import org.openapijsonschematools.schemas.validators.TypeValidator;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

public class SchemaValidator {
static final HashMap<String, KeywordValidator> keywordToValidator = new HashMap(){{
put("type", new TypeValidator());
}};
static PathToSchemasMap _validate(
Class<SchemaValidator> cls,
Object arg,
ValidationMetadata validationMetadata
) throws InstantiationException, IllegalAccessException {
SchemaValidator clsSchema = cls.newInstance();
Field[] fields = cls.getDeclaredFields();
HashMap<String, Object> fieldsToValues = new HashMap<>();
LinkedHashSet<String> disabledKeywords = validationMetadata.configuration().disabledKeywordFlags().getKeywords();
for (Field field : fields) {
String fieldName = field.getName();
if (disabledKeywords.contains(fieldName)) {
continue;
}
Object value = field.get(clsSchema);
fieldsToValues.put(fieldName, value);
}
PathToSchemasMap pathToSchemas = new PathToSchemasMap();
for (Map.Entry<String, Object> entry: fieldsToValues.entrySet()) {
String jsonKeyword = entry.getKey();
Object value = entry.getValue();
KeywordValidator validatorClass = keywordToValidator.get(jsonKeyword);
PathToSchemasMap otherPathToSchemas = validatorClass.validate(
arg,
value,
null,
cls,
validationMetadata
);
}
return pathToSchemas;
}
}
/**
* @classmethod
* def _validate(
* cls,
* arg,
* validation_metadata: ValidationMetadata,
* ) -> PathToSchemasType:
* """
* SchemaValidator validate
* All keyword validation except for type checking was done in calling stack frames
* If those validations passed, the validated classes are collected in path_to_schemas
* """
* cls_schema = cls()
* json_schema_data = {
* k: v
* for k, v in vars(cls_schema).items()
* if k not in cls.__excluded_cls_properties
* and k
* not in validation_metadata.configuration.disabled_json_schema_python_keywords
* }
* contains_path_to_schemas = []
* path_to_schemas: PathToSchemasType = {}
* if 'contains' in vars(cls_schema):
* contains_path_to_schemas = _get_contains_path_to_schemas(
* arg,
* vars(cls_schema)['contains'],
* validation_metadata,
* path_to_schemas
* )
* if_path_to_schemas = None
* if 'if_' in vars(cls_schema):
* if_path_to_schemas = _get_if_path_to_schemas(
* arg,
* vars(cls_schema)['if_'],
* validation_metadata,
* )
* validated_pattern_properties: typing.Optional[PathToSchemasType] = None
* if 'pattern_properties' in vars(cls_schema):
* validated_pattern_properties = _get_validated_pattern_properties(
* arg,
* vars(cls_schema)['pattern_properties'],
* cls,
* validation_metadata
* )
* prefix_items_length = 0
* if 'prefix_items' in vars(cls_schema):
* prefix_items_length = len(vars(cls_schema)['prefix_items'])
* for keyword, val in json_schema_data.items():
* used_val: typing.Any
* if keyword in {'contains', 'min_contains', 'max_contains'}:
* used_val = (val, contains_path_to_schemas)
* elif keyword == 'items':
* used_val = (val, prefix_items_length)
* elif keyword in {'unevaluated_items', 'unevaluated_properties'}:
* used_val = (val, path_to_schemas)
* elif keyword in {'types'}:
* format: typing.Optional[str] = vars(cls_schema).get('format', None)
* used_val = (val, format)
* elif keyword in {'pattern_properties', 'additional_properties'}:
* used_val = (val, validated_pattern_properties)
* elif keyword in {'if_', 'then', 'else_'}:
* used_val = (val, if_path_to_schemas)
* else:
* used_val = val
* validator = json_schema_keyword_to_validator[keyword]
*
* other_path_to_schemas = validator(
* arg,
* used_val,
* cls,
* validation_metadata,
*
* )
* if other_path_to_schemas:
* update(path_to_schemas, other_path_to_schemas)
*
* base_class = type(arg)
* if validation_metadata.path_to_item not in path_to_schemas:
* path_to_schemas[validation_metadata.path_to_item] = dict()
* path_to_schemas[validation_metadata.path_to_item][base_class] = None
* path_to_schemas[validation_metadata.path_to_item][cls] = None
* return path_to_schemas
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.openapijsonschematools.schemas;

import org.openapijsonschematools.configurations.SchemaConfiguration;
import java.util.List;
import java.util.Map;
import java.util.Set;

public record ValidationMetadata(
List<Object> pathToItem,
SchemaConfiguration configuration,
PathToSchemasMap validatedPathToSchemas,
Set<Class<?>> seenClasses
) {

protected boolean validationRanEarlier(Class<?> cls) {
Map<Class<?>, Void> validatedSchemas = validatedPathToSchemas.getOrDefault(pathToItem, null);
if (validatedSchemas != null && validatedSchemas.containsKey(cls)) {
return true;
}
if (seenClasses.contains(cls)) {
return true;
}
return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.openapijsonschematools.schemas.validators;

import org.openapijsonschematools.schemas.PathToSchemasMap;
import org.openapijsonschematools.schemas.SchemaValidator;
import org.openapijsonschematools.schemas.ValidationMetadata;

public interface KeywordValidator {
PathToSchemasMap validate(
Object arg,
Object value,
Object extra,
Class<SchemaValidator> cls,
ValidationMetadata validationMetadata);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.openapijsonschematools.schemas.validators;

import org.openapijsonschematools.schemas.PathToSchemasMap;
import org.openapijsonschematools.schemas.SchemaValidator;
import org.openapijsonschematools.schemas.ValidationMetadata;

import java.util.HashSet;

public class TypeValidator implements KeywordValidator {
@Override
public PathToSchemasMap validate(Object arg, Object value, Object extra, Class<SchemaValidator> cls, ValidationMetadata validationMetadata) {
HashSet<Class<?>> types = (HashSet<Class<?>>) value;
if (!types.contains(arg.getClass())) {
throw new RuntimeException("invalid type");
}
return null;
}
}
Loading