Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/added required nonnull check #1592

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@
* Task</a>
*/
public class Jsonschema2PojoTask extends Task implements GenerationConfig {

private boolean generateBuilders;
private boolean generateBuilders;

private boolean includeTypeInfo = false;

Expand Down Expand Up @@ -115,6 +115,8 @@ public class Jsonschema2PojoTask extends Task implements GenerationConfig {

private boolean includeJsr303Annotations = false;

private boolean includeRequireNonNullOnRequiredFields = false;

private boolean includeJsr305Annotations = false;

private boolean useOptionalForGetters;
Expand Down Expand Up @@ -947,6 +949,10 @@ public void setCustomDateTimePattern(String customDateTimePattern) {
public void setRefFragmentPathDelimiters(String refFragmentPathDelimiters) {
this.refFragmentPathDelimiters = refFragmentPathDelimiters;
}

public void setIncludeRequireNonNullOnRequiredFields(boolean includeRequireNonNullOnRequiredFields) {
this.includeRequireNonNullOnRequiredFields = includeRequireNonNullOnRequiredFields;
}

/**
* Sets the 'sourceSortOrder' property of this class
Expand Down Expand Up @@ -1338,4 +1344,8 @@ public boolean isIncludeGeneratedAnnotation() {
public boolean isUseJakartaValidation() {
return useJakartaValidation;
}
@Override
public boolean isIncludeRequireNonNullOnRequiredFields() {
return includeRequireNonNullOnRequiredFields;
}
}
6 changes: 6 additions & 0 deletions jsonschema2pojo-ant/src/site/Jsonschema2PojoTask.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ <h3>Parameters</h3>
</td>
<td align="center" valign="top">No (default <code>true</code>)</td>
</tr>
<tr>
<td valign="top"><a id="includeRequireNonNullOnRequiredFields"></a>includeRequireNonNullOnRequiredFields</td>
<td valign="top">Whether to include <code>java.util.Objects.requireNonNull(property)</code> in each setter for required field
</td>
<td align="center" valign="top">No (default <code>false</code>)</td>
</tr>
<tr>
<td valign="top"><a id="includeJsr303Annotations"></a>includeJsr303Annotations</td>
<td valign="top">Whether to include <a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ public class Arguments implements GenerationConfig {

@Parameter(names = { "-303", "--jsr303-annotations" }, description = "Add JSR-303/349 annotations to generated Java types.")
private boolean includeJsr303Annotations = false;
@Parameter(names = { "-RN", "--require-nonnull-check" }, description = "Add JSR-303/349 annotations to generated Java types.")
private boolean includeRequireNonNullOnRequiredFields = false;

@Parameter(names = { "-305", "--jsr305-annotations" }, description = "Add JSR-305 annotations to generated Java types.")
private boolean includeJsr305Annotations = false;
Expand Down Expand Up @@ -394,6 +396,11 @@ public Class<? extends RuleFactory> getCustomRuleFactory() {
return customRuleFactory;
}

@Override
public boolean isIncludeRequireNonNullOnRequiredFields() {
return includeRequireNonNullOnRequiredFields;
}

@Override
public boolean isIncludeJsr303Annotations() {
return includeJsr303Annotations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,4 +495,9 @@ public boolean isIncludeGeneratedAnnotation() {
public boolean isUseJakartaValidation() {
return false;
}

@Override
public boolean isIncludeRequireNonNullOnRequiredFields() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ public interface GenerationConfig {
* generated Java types.
*/
boolean isIncludeJsr305Annotations();
/**
* Gets the 'includeRequireNonNullOnRequiredFields' configuration option.
*
* @return Whether to add non-null check in setter method on given field.
*/
boolean isIncludeRequireNonNullOnRequiredFields();

/**
* Gets the 'useOptionalForGetters' configuration option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ public JFieldVar apply(String nodeName, JsonNode node, JsonNode parent, JFieldVa
} else if (fieldType.startsWith(String.class.getName()) && node != null ) {
field.init(getDefaultValue(field.type(), node));
} else if (defaultPresent) {
boolean requireNonNullCheck = (ruleFactory.getGenerationConfig().isIncludeRequireNonNullOnRequiredFields() && isRequired(nodeName, node, currentSchema));
if (requireNonNullCheck) {

if (field.type() instanceof JDefinedClass && ((JDefinedClass) field.type()).getClassType().equals(ClassType.ENUM)) {
field.annotate(SuppressWarnings.class).param("value", "null");
}
}
field.init(getDefaultValue(field.type(), node));

}
Expand All @@ -107,6 +114,9 @@ static JExpression getDefaultValue(JType fieldType, JsonNode node) {
return getDefaultValue(fieldType, node.asText());
}

private boolean isRequired(String nodeName, JsonNode node, Schema schema) {
return PropertyRule.isRequired(nodeName, node, schema);
}
static JExpression getDefaultValue(JType fieldType, String value) {

fieldType = fieldType.unboxify();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JDocCommentable;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;

import java.util.Objects;

import org.apache.commons.lang.StringUtils;

/**
Expand Down Expand Up @@ -99,20 +104,21 @@ public JDefinedClass apply(String nodeName, JsonNode node, JsonNode parent, JDef

ruleFactory.getAnnotator().propertyField(field, jclass, nodeName, node);

boolean required = isRequired(nodeName, node, schema);
if (isIncludeGetters) {
JMethod getter = addGetter(jclass, field, nodeName, node, isRequired(nodeName, node, schema), useOptional(nodeName, node, schema));
JMethod getter = addGetter(jclass, field, nodeName, node, required, useOptional(nodeName, node, schema));
ruleFactory.getAnnotator().propertyGetter(getter, jclass, nodeName);
propertyAnnotations(nodeName, node, schema, getter);
}

if (isIncludeSetters) {
JMethod setter = addSetter(jclass, field, nodeName, node);
JMethod setter = addSetter(jclass, field, nodeName, node, required);
ruleFactory.getAnnotator().propertySetter(setter, jclass, nodeName);
propertyAnnotations(nodeName, node, schema, setter);
}

if (ruleFactory.getGenerationConfig().isGenerateBuilders()) {
addBuilderMethod(jclass, field, nodeName, node);
addBuilderMethod(jclass, field, nodeName, node, required);
}

if (node.has("pattern")) {
Expand All @@ -136,7 +142,7 @@ public JDefinedClass apply(String nodeName, JsonNode node, JsonNode parent, JDef
return jclass;
}

private boolean hasEnumerated(Schema schema, String arrayFieldName, String nodeName) {
protected static boolean hasEnumerated(Schema schema, String arrayFieldName, String nodeName) {
JsonNode array = schema.getContent().get(arrayFieldName);
if (array != null) {
for (JsonNode requiredNode : array) {
Expand All @@ -148,7 +154,7 @@ private boolean hasEnumerated(Schema schema, String arrayFieldName, String nodeN
return false;
}

private boolean hasFlag(JsonNode node, String fieldName) {
protected static boolean hasFlag(JsonNode node, String fieldName) {
if (node.has(fieldName)) {
final JsonNode requiredNode = node.get(fieldName);
return requiredNode.asBoolean();
Expand All @@ -157,15 +163,15 @@ private boolean hasFlag(JsonNode node, String fieldName) {
return false;
}

private boolean isDeclaredAs(String type, String nodeName, JsonNode node, Schema schema) {
protected static boolean isDeclaredAs(String type, String nodeName, JsonNode node, Schema schema) {
return hasEnumerated(schema, type, nodeName) || hasFlag(node, type);
}

private boolean isRequired(String nodeName, JsonNode node, Schema schema) {
protected static boolean isRequired(String nodeName, JsonNode node, Schema schema) {
return isDeclaredAs("required", nodeName, node, schema);
}

private boolean useOptional(String nodeName, JsonNode node, Schema schema) {
protected static boolean useOptional(String nodeName, JsonNode node, Schema schema) {
return isDeclaredAs("javaOptional", nodeName, node, schema);
}

Expand Down Expand Up @@ -256,44 +262,55 @@ private JMethod addGetter(JDefinedClass c, JFieldVar field, String jsonPropertyN
return getter;
}

private JMethod addSetter(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node) {
private JMethod addSetter(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node, boolean required) {
JMethod setter = c.method(JMod.PUBLIC, void.class, getSetterName(jsonPropertyName, node));

JVar param = setter.param(field.type(), field.name());
JBlock body = setter.body();
addRequireNonNullCheck(c, field, required, param, body);
body.assign(JExpr._this().ref(field), param);

return setter;
}

private JMethod addBuilderMethod(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node) {
public void addRequireNonNullCheck(JDefinedClass c, JFieldVar field, boolean required, JVar param, JBlock body) {
if (required && ruleFactory.getGenerationConfig().isIncludeRequireNonNullOnRequiredFields()) {
JClass ref = c.owner().ref(Objects.class);
JInvocation staticInvoke = ref.staticInvoke("requireNonNull").arg(param).arg(c.fullName()+"#"+ field.name()+" must not be null");
body.add(staticInvoke);
}
}

private JMethod addBuilderMethod(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node, boolean required) {
JMethod result = null;
if(ruleFactory.getGenerationConfig().isUseInnerClassBuilders()) {
result = addInnerBuilderMethod(c, field, jsonPropertyName, node);
result = addInnerBuilderMethod(c, field, jsonPropertyName, node, required);
} else {
result = addLegacyBuilder(c, field, jsonPropertyName, node);
result = addLegacyBuilder(c, field, jsonPropertyName, node, required);
}
return result;
}

private JMethod addLegacyBuilder(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node) {
private JMethod addLegacyBuilder(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node, boolean required) {
JMethod builder = c.method(JMod.PUBLIC, c, getBuilderName(jsonPropertyName, node));

JVar param = builder.param(field.type(), field.name());
JBlock body = builder.body();
addRequireNonNullCheck(c, field, required, param, body);
body.assign(JExpr._this().ref(field), param);
body._return(JExpr._this());

return builder;
}

private JMethod addInnerBuilderMethod(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node) {
private JMethod addInnerBuilderMethod(JDefinedClass c, JFieldVar field, String jsonPropertyName, JsonNode node, boolean required) {
JDefinedClass builderClass = ruleFactory.getReflectionHelper().getBaseBuilderClass(c);

JMethod builderMethod = builderClass.method(JMod.PUBLIC, builderClass, getBuilderName(jsonPropertyName, node));

JVar param = builderMethod.param(field.type(), field.name());
JBlock body = builderMethod.body();
addRequireNonNullCheck(c, field, required, param, body);
body.assign(JExpr.ref(JExpr.cast(c, JExpr._this().ref("instance")), field), param);
body._return(JExpr._this());

Expand Down
3 changes: 2 additions & 1 deletion jsonschema2pojo-gradle-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ jsonSchema2Pojo {

// Whether to include JSR-305 annotations, for schema rules like Nullable, NonNull, etc
includeJsr305Annotations = false

// Whether to add Objects.requireNonNull in setter
includeRequireNonNullOnRequiredFields = false
// The Level of inclusion to set in the generated Java types (for Jackson serializers)
inclusionLevel = InclusionLevel.NON_NULL

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ public class JsonSchemaExtension implements GenerationConfig {
Map<String, String> formatTypeMapping
boolean includeGeneratedAnnotation
boolean useJakartaValidation
boolean includeRequireNonNullOnRequiredFields


public JsonSchemaExtension() {
// See DefaultGenerationConfig
Expand Down Expand Up @@ -150,6 +152,7 @@ public class JsonSchemaExtension implements GenerationConfig {
includeDynamicGetters = false
includeDynamicSetters = false
includeDynamicBuilders = false
includeRequireNonNullOnRequiredFields = false
formatDates = false
formatTimes = false
formatDateTimes = false
Expand Down Expand Up @@ -255,6 +258,7 @@ public class JsonSchemaExtension implements GenerationConfig {
|customAnnotator = ${customAnnotator.getName()}
|customRuleFactory = ${customRuleFactory.getName()}
|includeJsr303Annotations = ${includeJsr303Annotations}
|includeRequireNonNullOnRequiredFields = ${includeRequireNonNullOnRequiredFields}
|includeJsr305Annotations = ${includeJsr305Annotations}
|useOptionalForGetters = ${useOptionalForGetters}
|sourceType = ${sourceType.toString().toLowerCase()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,10 @@ public class Jsonschema2PojoMojo extends AbstractMojo implements GenerationConfi
*/
@Parameter(property = "jsonschema2pojo.includeJsr303Annotations", defaultValue = "false")
private boolean includeJsr303Annotations = false;



@Parameter(property = "jsonschema2pojo.includeRequireNonNullOnRequiredFields", defaultValue = "false")
private boolean includeRequireNonNullOnRequiredFields = false;
/**
* Whether to include
* <a href="http://jcp.org/en/jsr/detail?id=305">JSR-305</a> annotations
Expand Down Expand Up @@ -992,6 +995,10 @@ public Class<? extends RuleFactory> getCustomRuleFactory() {
}
}

@Override
public boolean isIncludeRequireNonNullOnRequiredFields() {
return includeRequireNonNullOnRequiredFields;
}
@Override
public boolean isIncludeJsr303Annotations() {
return includeJsr303Annotations;
Expand Down