Skip to content

Commit

Permalink
chore: refactor to improve code health (#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
CarstenWickner authored Nov 12, 2023
1 parent 81470da commit c1744cf
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -148,32 +149,37 @@ public static ObjectNode collectTypeAttributes(TypeScope scope, SchemaGeneration
collector.setDescription(node, config.resolveDescriptionForType(scope), generationContext);
collector.setDefault(node, config.resolveDefaultForType(scope), generationContext);
collector.setEnum(node, config.resolveEnumForType(scope), generationContext);
if (allowedSchemaTypes.isEmpty() || allowedSchemaTypes.contains(config.getKeyword(SchemaKeyword.TAG_TYPE_OBJECT))) {
if (isListEmptyOrContainingAtLeastOne(allowedSchemaTypes, config, SchemaKeyword.TAG_TYPE_OBJECT)) {
collector.setAdditionalProperties(node, config.resolveAdditionalPropertiesForType(scope, generationContext), generationContext);
collector.setPatternProperties(node, config.resolvePatternPropertiesForType(scope, generationContext), generationContext);
}
if (allowedSchemaTypes.isEmpty() || allowedSchemaTypes.contains(config.getKeyword(SchemaKeyword.TAG_TYPE_STRING))) {
if (isListEmptyOrContainingAtLeastOne(allowedSchemaTypes, config, SchemaKeyword.TAG_TYPE_STRING)) {
collector.setStringMinLength(node, config.resolveStringMinLengthForType(scope), generationContext);
collector.setStringMaxLength(node, config.resolveStringMaxLengthForType(scope), generationContext);
collector.setStringFormat(node, config.resolveStringFormatForType(scope), generationContext);
collector.setStringPattern(node, config.resolveStringPatternForType(scope), generationContext);
}
if (allowedSchemaTypes.isEmpty() || allowedSchemaTypes.contains(config.getKeyword(SchemaKeyword.TAG_TYPE_INTEGER))
|| allowedSchemaTypes.contains(config.getKeyword(SchemaKeyword.TAG_TYPE_NUMBER))) {
if (isListEmptyOrContainingAtLeastOne(allowedSchemaTypes, config, SchemaKeyword.TAG_TYPE_INTEGER, SchemaKeyword.TAG_TYPE_NUMBER)) {
collector.setNumberInclusiveMinimum(node, config.resolveNumberInclusiveMinimumForType(scope), generationContext);
collector.setNumberExclusiveMinimum(node, config.resolveNumberExclusiveMinimumForType(scope), generationContext);
collector.setNumberInclusiveMaximum(node, config.resolveNumberInclusiveMaximumForType(scope), generationContext);
collector.setNumberExclusiveMaximum(node, config.resolveNumberExclusiveMaximumForType(scope), generationContext);
collector.setNumberMultipleOf(node, config.resolveNumberMultipleOfForType(scope), generationContext);
}
if (allowedSchemaTypes.isEmpty() || allowedSchemaTypes.contains(config.getKeyword(SchemaKeyword.TAG_TYPE_ARRAY))) {
if (isListEmptyOrContainingAtLeastOne(allowedSchemaTypes, config, SchemaKeyword.TAG_TYPE_ARRAY)) {
collector.setArrayMinItems(node, config.resolveArrayMinItemsForType(scope), generationContext);
collector.setArrayMaxItems(node, config.resolveArrayMaxItemsForType(scope), generationContext);
collector.setArrayUniqueItems(node, config.resolveArrayUniqueItemsForType(scope), generationContext);
}
return node;
}

private static boolean isListEmptyOrContainingAtLeastOne(Set<String> values, SchemaGeneratorConfig config, SchemaKeyword... keywords) {
return values.isEmpty() || Stream.of(keywords)
.map(config::getKeyword)
.anyMatch(values::contains);
}

/**
* Merge the second node's attributes into the first, skipping those attributes that are already contained in the first node.
*
Expand Down Expand Up @@ -297,25 +303,7 @@ public AttributeCollector setDescription(ObjectNode node, String description, Sc
public AttributeCollector setDefault(ObjectNode node, Object defaultValue) {
if (defaultValue != null) {
final String defaultTag = SchemaKeyword.TAG_DEFAULT.forVersion(SchemaVersion.DRAFT_7);
// need to specifically add simple/primitive values by type
if (defaultValue instanceof String) {
node.put(defaultTag, (String) defaultValue);
} else if (defaultValue instanceof BigDecimal) {
node.put(defaultTag, (BigDecimal) defaultValue);
} else if (defaultValue instanceof BigInteger) {
node.put(defaultTag, (BigInteger) defaultValue);
} else if (defaultValue instanceof Boolean) {
node.put(defaultTag, (Boolean) defaultValue);
} else if (defaultValue instanceof Double) {
node.put(defaultTag, (Double) defaultValue);
} else if (defaultValue instanceof Float) {
node.put(defaultTag, (Float) defaultValue);
} else if (defaultValue instanceof Integer) {
node.put(defaultTag, (Integer) defaultValue);
} else {
// everything else is simply forwarded as-is to the JSON Schema, it's up to the configurator to ensure the value's correctness
node.putPOJO(defaultTag, defaultValue);
}
this.addRawPropertyValue(node, defaultTag, defaultValue);
}
return this;
}
Expand All @@ -331,25 +319,7 @@ public AttributeCollector setDefault(ObjectNode node, Object defaultValue) {
public AttributeCollector setDefault(ObjectNode node, Object defaultValue, SchemaGenerationContext generationContext) {
if (defaultValue != null) {
final String defaultTag = generationContext.getKeyword(SchemaKeyword.TAG_DEFAULT);
// need to specifically add simple/primitive values by type
if (defaultValue instanceof String) {
node.put(defaultTag, (String) defaultValue);
} else if (defaultValue instanceof BigDecimal) {
node.put(defaultTag, (BigDecimal) defaultValue);
} else if (defaultValue instanceof BigInteger) {
node.put(defaultTag, (BigInteger) defaultValue);
} else if (defaultValue instanceof Boolean) {
node.put(defaultTag, (Boolean) defaultValue);
} else if (defaultValue instanceof Double) {
node.put(defaultTag, (Double) defaultValue);
} else if (defaultValue instanceof Float) {
node.put(defaultTag, (Float) defaultValue);
} else if (defaultValue instanceof Integer) {
node.put(defaultTag, (Integer) defaultValue);
} else {
// everything else is simply forwarded as-is to the JSON Schema, it's up to the configurator to ensure the value's correctness
node.putPOJO(defaultTag, defaultValue);
}
this.addRawPropertyValue(node, defaultTag, defaultValue);
}
return this;
}
Expand All @@ -371,21 +341,10 @@ public AttributeCollector setEnum(ObjectNode node, Collection<?> enumValues) {
.filter(this::canBeConvertedToString)
.collect(Collectors.toList());
if (values.size() == 1) {
Object singleValue = values.get(0);
if (singleValue instanceof String) {
node.put(SchemaKeyword.TAG_CONST.forVersion(schemaVersion), (String) singleValue);
} else {
node.putPOJO(SchemaKeyword.TAG_CONST.forVersion(schemaVersion), singleValue);
}
this.addRawPropertyValue(node, SchemaKeyword.TAG_CONST.forVersion(schemaVersion), values.get(0));
} else if (!values.isEmpty()) {
ArrayNode array = node.arrayNode();
for (Object singleValue : values) {
if (singleValue instanceof String) {
array.add((String) singleValue);
} else {
array.addPOJO(singleValue);
}
}
values.forEach(singleValue -> this.addRawArrayItem(array, singleValue));
node.set(SchemaKeyword.TAG_ENUM.forVersion(schemaVersion), array);
}
}
Expand All @@ -401,31 +360,67 @@ public AttributeCollector setEnum(ObjectNode node, Collection<?> enumValues) {
* @return this instance (for chaining)
*/
public AttributeCollector setEnum(ObjectNode node, Collection<?> enumValues, SchemaGenerationContext generationContext) {
if (enumValues != null) {
List<Object> values = enumValues.stream()
.filter(this::isSupportedEnumValue)
.filter(this::canBeConvertedToString)
.collect(Collectors.toList());
if (values.size() == 1 && generationContext.getGeneratorConfig().shouldRepresentSingleAllowedValueAsConst()) {
Object singleValue = values.get(0);
if (singleValue instanceof String) {
node.put(generationContext.getKeyword(SchemaKeyword.TAG_CONST), (String) singleValue);
} else {
node.putPOJO(generationContext.getKeyword(SchemaKeyword.TAG_CONST), singleValue);
}
} else if (!values.isEmpty()) {
ArrayNode array = node.arrayNode();
for (Object singleValue : values) {
if (singleValue instanceof String) {
array.add((String) singleValue);
} else {
array.addPOJO(singleValue);
}
}
node.set(generationContext.getKeyword(SchemaKeyword.TAG_ENUM), array);
}
if (enumValues == null) {
return this;
}
List<Object> values = enumValues.stream()
.filter(this::isSupportedEnumValue)
.filter(this::canBeConvertedToString)
.collect(Collectors.toList());
if (values.size() == 1 && generationContext.getGeneratorConfig().shouldRepresentSingleAllowedValueAsConst()) {
this.addRawPropertyValue(node, generationContext.getKeyword(SchemaKeyword.TAG_CONST), values.get(0));
} else if (!values.isEmpty()) {
ArrayNode array = node.arrayNode();
values.forEach(singleValue -> this.addRawArrayItem(array, singleValue));
node.set(generationContext.getKeyword(SchemaKeyword.TAG_ENUM), array);
}
return this;
}

private void addRawPropertyValue(ObjectNode node, String propertyName, Object value) {
// need to specifically add simple/primitive values by type
if (value instanceof String) {
// explicit inclusion as string results in wrapping quote symbols
node.put(propertyName, (String) value);
} else if (value instanceof BigDecimal) {
node.put(propertyName, (BigDecimal) value);
} else if (value instanceof BigInteger) {
node.put(propertyName, (BigInteger) value);
} else if (value instanceof Boolean) {
node.put(propertyName, (Boolean) value);
} else if (value instanceof Double) {
node.put(propertyName, (Double) value);
} else if (value instanceof Float) {
node.put(propertyName, (Float) value);
} else if (value instanceof Integer) {
node.put(propertyName, (Integer) value);
} else {
// everything else is simply forwarded as-is to the JSON Schema, it's up to the configurator to ensure the value's correctness
node.putPOJO(propertyName, value);
}
}

private void addRawArrayItem(ArrayNode node, Object value) {
// need to specifically add simple/primitive values by type
if (value instanceof String) {
// explicit inclusion as string results in wrapping quote symbols
node.add((String) value);
} else if (value instanceof BigDecimal) {
node.add((BigDecimal) value);
} else if (value instanceof BigInteger) {
node.add((BigInteger) value);
} else if (value instanceof Boolean) {
node.add((Boolean) value);
} else if (value instanceof Double) {
node.add((Double) value);
} else if (value instanceof Float) {
node.add((Float) value);
} else if (value instanceof Integer) {
node.add((Integer) value);
} else {
// everything else is simply forwarded as-is to the JSON Schema, it's up to the configurator to ensure the value's correctness
node.addPOJO(value);
}
return this;
}

/**
Expand Down Expand Up @@ -499,12 +494,18 @@ public AttributeCollector setWriteOnly(ObjectNode node, boolean writeOnly, Schem
* @return this instance (for chaining)
*/
public AttributeCollector setAdditionalProperties(ObjectNode node, JsonNode additionalProperties, SchemaGenerationContext generationContext) {
if (additionalProperties != null && (!additionalProperties.isBoolean() || !additionalProperties.asBoolean())) {
if (!this.isNullOrTrue(additionalProperties)) {
node.set(generationContext.getKeyword(SchemaKeyword.TAG_ADDITIONAL_PROPERTIES), additionalProperties);
}
return this;
}

private boolean isNullOrTrue(JsonNode nodeToCheck) {
return nodeToCheck == null
|| nodeToCheck.isNull()
|| nodeToCheck.isBoolean() && nodeToCheck.asBoolean();
}

/**
* Setter for "{@link SchemaKeyword#TAG_PATTERN_PROPERTIES}" attribute.
*
Expand Down
Loading

0 comments on commit c1744cf

Please sign in to comment.