Skip to content

Commit

Permalink
AVRO-3641: Adds support for nullSafeAnnotations to java SpecificCompi…
Browse files Browse the repository at this point in the history
…ler (apache#2142)

* AVRO-3641: Adds support for nullSafeAnnotations to java SpecificCompiler

* AVRO-3641: Removes maven dependency to org.jetbrains:annotations since it is only used in the produced jar

* AVRO-3641: Removes the unused property for jetbrains-annotations version

* AVRO-3641: Removes empty lines from expected output file

* Revert "AVRO-3641: Removes empty lines from expected output file"

This reverts commit f99cf16.

* AVRO-3641: Use full class name for null safe annotations instead of imports

* AVRO-3641: Adds avro-maven-plugin config parameter for createNullSafeAnnotations

* AVRO-3641: Clarifies the source of the nullability annotations

* AVRO-3641: Minor javadoc formatting.

* AVRO-3641: Fixes spotless formatting

* AVRO-3641: Adds license exclude for NullSafeAnnotationsFieldsTest.java

---------

Co-authored-by: pknu <[email protected]>
  • Loading branch information
2 people authored and Ranbir Kumar committed May 13, 2024
1 parent 2a1f3af commit b255b43
Show file tree
Hide file tree
Showing 8 changed files with 663 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ void addLogicalTypeConversions(SpecificData specificData) {
private boolean gettersReturnOptional = false;
private boolean optionalGettersForNullableFieldsOnly = false;
private boolean createSetters = true;
private boolean createNullSafeAnnotations = false;
private boolean createAllArgsConstructor = true;
private String outputCharacterEncoding;
private boolean enableDecimalLogicalType = false;
Expand Down Expand Up @@ -262,6 +263,17 @@ public void setCreateSetters(boolean createSetters) {
this.createSetters = createSetters;
}

public boolean isCreateNullSafeAnnotations() {
return this.createNullSafeAnnotations;
}

/**
* Set to true to add jetbrains @Nullable and @NotNull annotations
*/
public void setCreateNullSafeAnnotations(boolean createNullSafeAnnotations) {
this.createNullSafeAnnotations = createNullSafeAnnotations;
}

public boolean isCreateOptionalGetters() {
return this.createOptionalGetters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public class ${this.mangleTypeIdentifier($schema.getName())} extends ${this.getS
#end
#end
*/
public ${this.mangleTypeIdentifier($schema.getName())}(#foreach($field in $schema.getFields())${this.javaType($field.schema())} ${this.mangle($field.name())}#if($foreach.count < $schema.getFields().size()), #end#end) {
public ${this.mangleTypeIdentifier($schema.getName())}(#foreach($field in $schema.getFields())#if(${this.createNullSafeAnnotations})#if(${field.schema().isNullable()})@org.jetbrains.annotations.Nullable#[email protected]#end #end${this.javaType($field.schema())} ${this.mangle($field.name())}#if($foreach.count < $schema.getFields().size()), #end#end) {
#foreach ($field in $schema.getFields())
${this.generateSetterCode($field.schema(), ${this.mangle($field.name())}, ${this.mangle($field.name())})}
#end
Expand Down Expand Up @@ -243,6 +243,13 @@ public class ${this.mangleTypeIdentifier($schema.getName())} extends ${this.getS
#else * @return The value of the '${this.mangle($field.name(), $schema.isError())}' field.
#end
*/
#if(${this.createNullSafeAnnotations})
#if (${field.schema().isNullable()})
@org.jetbrains.annotations.Nullable
#else
@org.jetbrains.annotations.NotNull
#end
#end
public ${this.javaUnbox($field.schema(), false)} ${this.generateGetMethod($schema, $field)}() {
return ${this.mangle($field.name(), $schema.isError())};
}
Expand All @@ -267,7 +274,7 @@ public class ${this.mangleTypeIdentifier($schema.getName())} extends ${this.getS
#end
* @param value the value to set.
*/
public void ${this.generateSetMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)} value) {
public void ${this.generateSetMethod($schema, $field)}(#if(${this.createNullSafeAnnotations})#if(${field.schema().isNullable()})@org.jetbrains.annotations.Nullable#[email protected]#end #end${this.javaUnbox($field.schema(), false)} value) {
${this.generateSetterCode($field.schema(), ${this.mangle($field.name(), $schema.isError())}, "value")}
}
#end
Expand Down Expand Up @@ -423,7 +430,7 @@ public class ${this.mangleTypeIdentifier($schema.getName())} extends ${this.getS
* @param value The value of '${this.mangle($field.name(), $schema.isError())}'.
* @return This builder.
*/
public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangleTypeIdentifier($schema.getName())}.Builder ${this.generateSetMethod($schema, $field)}(${this.javaUnbox($field.schema(), false)} value) {
public #if ($schema.getNamespace())$this.mangle($schema.getNamespace()).#end${this.mangleTypeIdentifier($schema.getName())}.Builder ${this.generateSetMethod($schema, $field)}(#if(${this.createNullSafeAnnotations})#if(${field.schema().isNullable()})@org.jetbrains.annotations.Nullable#[email protected]#end #end${this.javaUnbox($field.schema(), false)} value) {
validate(fields()[$field.pos()], value);
#if (${this.hasBuilder($field.schema())})
this.${this.mangle($field.name(), $schema.isError())}Builder = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,19 @@ public abstract class AbstractAvroMojo extends AbstractMojo {
*/
protected boolean createSetters;

/**
* The createNullSafeAnnotations parameter adds JetBrains {@literal @}Nullable
* and {@literal @}NotNull annotations for fhe fields of the record. The default
* is to not include annotations.
*
* @parameter property="createNullSafeAnnotations"
*
* @see <a href=
* "https://www.jetbrains.com/help/idea/annotating-source-code.html#nullability-annotations">
* JetBrains nullability annotations</a>
*/
protected boolean createNullSafeAnnotations = false;

/**
* A set of fully qualified class names of custom
* {@link org.apache.avro.Conversion} implementations to add to the compiler.
Expand Down Expand Up @@ -391,6 +404,7 @@ private void doCompile(File sourceFileForModificationDetection, SpecificCompiler
compiler.setGettersReturnOptional(gettersReturnOptional);
compiler.setOptionalGettersForNullableFieldsOnly(optionalGettersForNullableFieldsOnly);
compiler.setCreateSetters(createSetters);
compiler.setCreateNullSafeAnnotations(createNullSafeAnnotations);
compiler.setEnableDecimalLogicalType(enableDecimalLogicalType);
try {
for (String customConversion : customConversions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ public int run(InputStream in, PrintStream out, PrintStream err, List<String> or
if (origArgs.size() < 3) {
System.err
.println("Usage: [-encoding <outputencoding>] [-string] [-bigDecimal] [-fieldVisibility <visibilityType>] "
+ "[-noSetters] [-addExtraOptionalGetters] [-optionalGetters <optionalGettersType>] "
+ "[-noSetters] [-nullSafeAnnotations] [-addExtraOptionalGetters] [-optionalGetters <optionalGettersType>] "
+ "[-templateDir <templateDir>] (schema|protocol) input... outputdir");
System.err.println(" input - input files or directories");
System.err.println(" outputdir - directory to write generated java");
System.err.println(" -encoding <outputencoding> - set the encoding of " + "output file(s)");
System.err.println(" -string - use java.lang.String instead of Utf8");
System.err.println(" -fieldVisibility [private|public] - use either and default private");
System.err.println(" -noSetters - do not generate setters");
System.err.println(" -nullSafeAnnotations - add @Nullable and @NotNull annotations");
System.err
.println(" -addExtraOptionalGetters - generate extra getters with this format: 'getOptional<FieldName>'");
System.err.println(
Expand All @@ -72,6 +73,7 @@ public int run(InputStream in, PrintStream out, PrintStream err, List<String> or
compilerOpts.stringType = StringType.CharSequence;
compilerOpts.useLogicalDecimal = false;
compilerOpts.createSetters = true;
compilerOpts.createNullSafeAnnotations = false;
compilerOpts.optionalGettersType = Optional.empty();
compilerOpts.addExtraOptionalGetters = false;
compilerOpts.encoding = Optional.empty();
Expand All @@ -85,6 +87,11 @@ public int run(InputStream in, PrintStream out, PrintStream err, List<String> or
args.remove(args.indexOf("-noSetters"));
}

if (args.contains("-nullSafeAnnotations")) {
compilerOpts.createNullSafeAnnotations = true;
args.remove(args.indexOf("-nullSafeAnnotations"));
}

if (args.contains("-addExtraOptionalGetters")) {
compilerOpts.addExtraOptionalGetters = true;
args.remove(args.indexOf("-addExtraOptionalGetters"));
Expand Down Expand Up @@ -172,6 +179,7 @@ private void executeCompiler(SpecificCompiler compiler, CompilerOptions opts, Fi
throws IOException {
compiler.setStringType(opts.stringType);
compiler.setCreateSetters(opts.createSetters);
compiler.setCreateNullSafeAnnotations(opts.createNullSafeAnnotations);

opts.optionalGettersType.ifPresent(choice -> {
compiler.setGettersReturnOptional(true);
Expand Down Expand Up @@ -267,6 +275,7 @@ private static class CompilerOptions {
Optional<FieldVisibility> fieldVisibility;
boolean useLogicalDecimal;
boolean createSetters;
boolean createNullSafeAnnotations;
boolean addExtraOptionalGetters;
Optional<OptionalGettersType> optionalGettersType;
Optional<String> templateDir;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"type":"record", "name":"NullSafeAnnotationsFieldsTest", "namespace": "avro.examples.baseball", "doc":"Test that @org.jetbrains.annotations.Nullable and @org.jetbrains.annotations.NotNull annotations are created for all fields",
"fields": [
{"name": "name", "type": "string"},
{"name": "nullable_name", "type": ["string", "null"]},
{"name": "favorite_number", "type": "int"},
{"name": "nullable_favorite_number", "type": ["int", "null"]}
]
}
Loading

0 comments on commit b255b43

Please sign in to comment.