Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

Add support for generating getters that return Optional #90

Merged
merged 2 commits into from
Oct 17, 2019
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
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ There are a number of configuration options supported in the `avro` block.
| option | default | description |
| --------------------------| --------------------- | ------------------------------------------------- |
| createSetters | `true` | `createSetters` passed to Avro compiler |
| createOptionalGetters | `false` | `createOptionalGetters` passed to Avro compiler |
| gettersReturnOptional | `false` | `gettersReturnOptional` passed to Avro compiler
| fieldVisibility | `"PUBLIC_DEPRECATED"` | `fieldVisibility` passed to Avro compiler |
| outputCharacterEncoding | see below | `outputCharacterEncoding` passed to Avro compiler |
| stringType | `"String"` | `stringType` passed to Avro compiler |
Expand All @@ -108,6 +110,40 @@ avro {
}
```

## createOptionalGetters

Valid values: `false` (default), `true`; supports equivalent `String` values

Set to `true` to create additional getter methods that return their fields wrapped in an
[Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html). For a field with
name `abc` and type `string`, this setting will create a method
`Optional<java.lang.String> getOptionalAbc()`.

Example:

```groovy
avro {
createOptionalGetters = false
}
```

## gettersReturnOptional

Valid values: `false` (default), `true`; supports equivalent `String` values

Set to `true` to cause getter methods to return
[Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) wrappers of the
underlying type. Where [`createOptionalGetters`](#createoptionalgetters) generates an additional
method, this one replaces the existing getter.

Example:

```groovy
avro {
gettersReturnOptional = false
}
```

## fieldVisibility

Valid values: any [FieldVisibility](http://avro.apache.org/docs/1.8.1/api/java/org/apache/avro/compiler/specific/SpecificCompiler.FieldVisibility.html) or equivalent `String` name (matched case-insensitively); default `"PUBLIC_DEPRECATED"` (default)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ private static void configureExtension(final Project project) {
configurePropertyConvention(task.getFieldVisibility(), avroExtension.getFieldVisibility());
configurePropertyConvention(task.getTemplateDirectory(), avroExtension.getTemplateDirectory());
configurePropertyConvention(task.isCreateSetters(), avroExtension.isCreateSetters());
configurePropertyConvention(task.isCreateOptionalGetters(), avroExtension.isCreateOptionalGetters());
configurePropertyConvention(task.isGettersReturnOptional(), avroExtension.isGettersReturnOptional());
configurePropertyConvention(task.isEnableDecimalLogicalType(), avroExtension.isEnableDecimalLogicalType());
configurePropertyConvention(task.getDateTimeLogicalType(), avroExtension.getDateTimeLogicalType());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public interface AvroExtension {
Property<String> getFieldVisibility();
Property<String> getTemplateDirectory();
Property<Boolean> isCreateSetters();
Property<Boolean> isCreateOptionalGetters();
Property<Boolean> isGettersReturnOptional();
Property<Boolean> isEnableDecimalLogicalType();
Property<String> getDateTimeLogicalType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Constants {
static final String DEFAULT_STRING_TYPE = StringType.String.name();
static final String DEFAULT_FIELD_VISIBILITY = FieldVisibility.PUBLIC_DEPRECATED.name();
static final boolean DEFAULT_CREATE_SETTERS = true;
static final boolean DEFAULT_CREATE_OPTIONAL_GETTERS = false;
static final boolean DEFAULT_GETTERS_RETURN_OPTIONAL = false;
static final boolean DEFAULT_ENABLE_DECIMAL_LOGICAL_TYPE = true;
static final String DEFAULT_DATE_TIME_LOGICAL_TYPE = SpecificCompiler.DateTimeLogicalTypeImplementation.DEFAULT.name();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;

import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_CREATE_OPTIONAL_GETTERS;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_CREATE_SETTERS;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_DATE_TIME_LOGICAL_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_ENABLE_DECIMAL_LOGICAL_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_FIELD_VISIBILITY;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_GETTERS_RETURN_OPTIONAL;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_STRING_TYPE;
import static com.commercehub.gradle.plugin.avro.GradleCompatibility.configurePropertyConvention;

Expand All @@ -35,6 +37,8 @@ public class DefaultAvroExtension implements AvroExtension {
private final Property<String> fieldVisibility;
private final Property<String> templateDirectory;
private final Property<Boolean> createSetters;
private final Property<Boolean> createOptionalGetters;
private final Property<Boolean> gettersReturnOptional;
private final Property<Boolean> enableDecimalLogicalType;
private final Property<String> dateTimeLogicalType;

Expand All @@ -45,6 +49,8 @@ public DefaultAvroExtension(ObjectFactory objects) {
this.fieldVisibility = configurePropertyConvention(objects.property(String.class), DEFAULT_FIELD_VISIBILITY);
this.templateDirectory = objects.property(String.class);
this.createSetters = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_CREATE_SETTERS);
this.createOptionalGetters = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_CREATE_OPTIONAL_GETTERS);
this.gettersReturnOptional = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_GETTERS_RETURN_OPTIONAL);
this.enableDecimalLogicalType = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_ENABLE_DECIMAL_LOGICAL_TYPE);
this.dateTimeLogicalType = configurePropertyConvention(objects.property(String.class), DEFAULT_DATE_TIME_LOGICAL_TYPE);
}
Expand Down Expand Up @@ -110,6 +116,32 @@ public void setCreateSetters(boolean createSetters) {
this.createSetters.set(createSetters);
}

@Override
public Property<Boolean> isCreateOptionalGetters() {
return createOptionalGetters;
}

public void setCreateOptionalGetters(String createOptionalGetters) {
setCreateOptionalGetters(Boolean.parseBoolean(createOptionalGetters));
}

public void setCreateOptionalGetters(boolean createOptionalGetters) {
this.createOptionalGetters.set(createOptionalGetters);
}

@Override
public Property<Boolean> isGettersReturnOptional() {
return gettersReturnOptional;
}

public void setGettersReturnOptional(String gettersReturnOptional) {
setGettersReturnOptional(Boolean.parseBoolean(gettersReturnOptional));
}

public void setGettersReturnOptional(boolean gettersReturnOptional) {
this.gettersReturnOptional.set(gettersReturnOptional);
}

@Override
public Property<Boolean> isEnableDecimalLogicalType() {
return enableDecimalLogicalType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;

import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_CREATE_OPTIONAL_GETTERS;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_CREATE_SETTERS;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_DATE_TIME_LOGICAL_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_ENABLE_DECIMAL_LOGICAL_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_FIELD_VISIBILITY;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_GETTERS_RETURN_OPTIONAL;
import static com.commercehub.gradle.plugin.avro.Constants.DEFAULT_STRING_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.OPTION_DATE_TIME_LOGICAL_TYPE;
import static com.commercehub.gradle.plugin.avro.Constants.OPTION_FIELD_VISIBILITY;
Expand All @@ -68,6 +70,8 @@ public class GenerateAvroJavaTask extends OutputDirTask {
private final Property<String> stringType;
private final Property<String> fieldVisibility;
private final Property<String> templateDirectory;
private final Property<Boolean> createOptionalGetters;
private final Property<Boolean> gettersReturnOptional;
private final Property<Boolean> createSetters;
private final Property<Boolean> enableDecimalLogicalType;
private final Property<String> dateTimeLogicalType;
Expand All @@ -83,6 +87,8 @@ public GenerateAvroJavaTask(ObjectFactory objects) {
this.stringType = configurePropertyConvention(objects.property(String.class), DEFAULT_STRING_TYPE);
this.fieldVisibility = configurePropertyConvention(objects.property(String.class), DEFAULT_FIELD_VISIBILITY);
this.templateDirectory = objects.property(String.class);
this.createOptionalGetters = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_CREATE_OPTIONAL_GETTERS);
this.gettersReturnOptional = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_GETTERS_RETURN_OPTIONAL);
this.createSetters = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_CREATE_SETTERS);
this.enableDecimalLogicalType = configurePropertyConvention(objects.property(Boolean.class), DEFAULT_ENABLE_DECIMAL_LOGICAL_TYPE);
this.dateTimeLogicalType = configurePropertyConvention(objects.property(String.class), DEFAULT_DATE_TIME_LOGICAL_TYPE);
Expand Down Expand Up @@ -158,6 +164,32 @@ public void setCreateSetters(String createSetters) {
this.createSetters.set(Boolean.parseBoolean(createSetters));
}

public Property<Boolean> isCreateOptionalGetters() {
return createOptionalGetters;
}

@Input
public Property<Boolean> getCreateOptionalGetters() {
return createOptionalGetters;
}

public void setCreateOptionalGetters(String createOptionalGetters) {
this.createOptionalGetters.set(Boolean.parseBoolean(createOptionalGetters));
}

public Property<Boolean> isGettersReturnOptional() {
return gettersReturnOptional;
}

@Input
public Property<Boolean> getGettersReturnOptional() {
return gettersReturnOptional;
}

public void setGettersReturnOptional(String gettersReturnOptional) {
this.gettersReturnOptional.set(Boolean.parseBoolean(gettersReturnOptional));
}

public Property<Boolean> isEnableDecimalLogicalType() {
return enableDecimalLogicalType;
}
Expand Down Expand Up @@ -192,6 +224,8 @@ protected void process() {
getLogger().debug("Using fieldVisibility {}", fieldVisibilityProvider.get().name());
getLogger().debug("Using templateDirectory '{}'", getTemplateDirectory().getOrNull());
getLogger().debug("Using createSetters {}", isCreateSetters().get());
getLogger().debug("Using createOptionalGetters {}", isCreateOptionalGetters().get());
getLogger().debug("Using gettersReturnOptional {}", isGettersReturnOptional().get());
getLogger().debug("Using enableDecimalLogicalType {}", isEnableDecimalLogicalType().get());
getLogger().debug("Using dateTimeLogicalType {}", dateTimeLogicalTypeImplementationProvider.get().name());
getLogger().info("Found {} files", getInputs().getSourceFiles().getFiles().size());
Expand Down Expand Up @@ -315,6 +349,8 @@ private void compile(SpecificCompiler compiler, File sourceFile) throws IOExcept
if (getTemplateDirectory().isPresent()) {
compiler.setTemplateDir(getTemplateDirectory().get());
}
compiler.setCreateOptionalGetters(createOptionalGetters.get());
compiler.setGettersReturnOptional(gettersReturnOptional.get());
compiler.setCreateSetters(isCreateSetters().get());
compiler.setEnableDecimalLogicalType(isEnableDecimalLogicalType().get());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ class OptionsFunctionalSpec extends FunctionalSpec {
and: "createSetters is enabled"
content.contains("public void setName(java.lang.String value)")

and: "createOptionalGetters is disabled"
!content.contains("Optional")

and: "gettersReturnOptional is disabled"
!content.contains("Optional")

and: "enableDecimalLogicalType is enabled"
content.contains("public void setSalary(${BigDecimal.name} value)")

Expand Down Expand Up @@ -153,6 +159,66 @@ class OptionsFunctionalSpec extends FunctionalSpec {
"'false'" | false
}

@Unroll
def "supports configuring createOptionalGetters to #createOptionalGetters"() {
given:
copyResource("user.avsc", avroDir)
buildFile << """
|avro {
| createOptionalGetters = ${createOptionalGetters}
|}
|""".stripMargin()

when:
def result = run("generateAvroJava")

then: "the task succeeds"
taskInfoAbsent || result.task(":generateAvroJava").outcome == SUCCESS
def content = projectFile("build/generated-main-avro-java/example/avro/User.java").text

and: "the specified createOptionalGetters is used"
content.contains("public Optional<java.lang.String> getOptionalFavoriteColor()") == expectedPresent

where:
createOptionalGetters | expectedPresent
"Boolean.TRUE" | true
"Boolean.FALSE" | false
"true" | true
"false" | false
"'true'" | true
"'false'" | false
}

@Unroll
def "supports configuring gettersReturnOptional to #gettersReturnOptional"() {
given:
copyResource("user.avsc", avroDir)
buildFile << """
|avro {
| gettersReturnOptional = ${gettersReturnOptional}
|}
|""".stripMargin()

when:
def result = run("generateAvroJava")

then: "the task succeeds"
taskInfoAbsent || result.task(":generateAvroJava").outcome == SUCCESS
def content = projectFile("build/generated-main-avro-java/example/avro/User.java").text

and: "the specified createOptionalGetters is used"
content.contains("public Optional<java.lang.String> getFavoriteColor()") == expectedPresent

where:
gettersReturnOptional | expectedPresent
"Boolean.TRUE" | true
"Boolean.FALSE" | false
"true" | true
"false" | false
"'true'" | true
"'false'" | false
}

def "supports configuring templateDirectory"() {
given:
def templatesDir = testProjectDir.newFolder("templates", "alternateTemplates")
Expand Down