Skip to content

Android, builders fluent setters, AutoValue #61

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

Open
wants to merge 4 commits into
base: main
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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,22 @@ Currently, the following examples exist:
* _mapstruct-examples-field-mapping_: Shows how MapStruct can be used with "struct" like objects with public fields
* _mapstruct-nested-bean-mappings_: Shows how to map object graphs via a main root method
* _mapstruct-mapping-with-cycles_: Shows how to map object graphs that can contain cycles
* _mapstruct-on-android-with-autovalue-builders_: Shows how MapStruct works with builders for immutable objects in an Android sample project.
* _mapstruct-spi-accessor-naming_: Example on how to use the Service Provider Interface (SPI) for a custom accessor naming strategy.
* _mapstruct-protobuf3_: Example on how to use protobuf3 with MapStruct
* _mapstruct-kotlin_: Example on how to use MapStruct with Kotlin using KAPT (Kotlin Annotation Processing Tool)
* _mapstruct-kotlin-gradle_: Example on how to use MapStruct with Kotlin and Gradle Kotlin DSL using KAPT
* _mapstruct-jpa-parent-child_: Example on how to use @Context in relation to parent / child relations in JPA)
* _mapstruct-jpa-parent-child_: Example on how to use @Context in relation to parent / child relations in JPA
* _mapstruct-suppress-unmapped_: Shows how mapping to target properties can be ignored without warning by default in a mixed scenario. However bean property mappings that have the same name will still be applied.
* _mapstruct-lookup-entity-with-composed-key_: Shows how an object with composite key can be read from the database in a mapping method.
* _mapstruct-clone_: Shows how an object can be deeply cloned by defining all mapping methods.
* _mapstruct-metadata-annotations_: Demonstrates how to read annotations and use them as mapping instruction.

# MapStruct Integration tests

The integration tests are also a valuable resource for inspecting how MapStruct works. Here is the entire collection [integration test resources](https://github.com/mapstruct/mapstruct/tree/master/integrationtest/src/test/resources)
and here is an example for [AutoValue](https://github.com/mapstruct/mapstruct/tree/master/integrationtest/src/test/resources/autoValueBuilderTest/src/main/java/org/mapstruct/itest/auto/value) as one of those integrations tests.

## License

The examples in this project are licensed under the Apache License, Version 2.0.
42 changes: 42 additions & 0 deletions mapstruct-on-android-with-autovalue-builders/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ IDEA module file
*.iml

# Intellij IDEA project settings folder
#.idea/workspace.xml
#.idea/tasks.xml
#.idea/datasources.xml
#.idea/dataSources.ids
.idea/
13 changes: 13 additions & 0 deletions mapstruct-on-android-with-autovalue-builders/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# mapstruct-test

This repository contains a sample project using [MapStruct](http://mapstruct.org/) on Android.

This sample project originates from [Albert Beade's MapStruct test at GitHub](https://github.com/abeade/mapstruct-test)

# How to run it

Open this containing folder with its android gradle build files directly in Android Studio.

## License

* [Apache Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
45 changes: 45 additions & 0 deletions mapstruct-on-android-with-autovalue-builders/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
plugins {
// https://plugins.gradle.org/plugin/net.ltgt.apt
id 'net.ltgt.apt' version '0.21' // mapstruct
}
// See more details: https://github.com/tbroyer/gradle-apt-plugin#usage-with-ides
apply plugin: 'net.ltgt.apt-idea' // mapstruct
//apply plugin: 'net.ltgt.apt-eclipse' // Not needed with android studio

apply plugin: 'com.android.application'

android {
compileSdkVersion 28

defaultConfig {
applicationId "com.example.mapstructtest"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
compileOptions {
// Just here to demonstrate it compiles with this. Java 8 allows use of repeated annotations,
// See AutoValueMapper.java for more comments on this
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0' // Just for this example
implementation 'org.mapstruct:mapstruct:1.3.0.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.0.Final'
// If mappers generated in test code
// testAnnotationProcessor 'org.mapstruct:mapstruct-processor:1.3.0.Final'

// For tests of mapstruct with AutoValue
compileOnly "com.google.auto.value:auto-value:1.5.2"
annotationProcessor "com.google.auto.value:auto-value:1.5.2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Alberto\Documents\Development\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mapstructtest" >

<application
android:allowBackup="true"
android:label="MapStruct Test"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar" >
<activity
android:name=".MainActivity"
android:screenOrientation="landscape"
android:label="MapStruct Test" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.example.mapstructtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import com.example.mapstructtest.model.AutoValueCar;
import com.example.mapstructtest.model.AutoValueCarDto;
import com.example.mapstructtest.model.AutoValueFluentCar;
import com.example.mapstructtest.model.AutoValueFluentCarDto;
import com.example.mapstructtest.model.Car;
import com.example.mapstructtest.model.CarDto;
import com.example.mapstructtest.model.CarFluentSetter;
import com.example.mapstructtest.model.CarType;
import com.example.mapstructtest.model.ImmutableConstructableCar;
import com.example.mapstructtest.model.ImmutableConstructibleCarDto;
import com.example.mapstructtest.model.mapping.AutoValueFluentMapper;
import com.example.mapstructtest.model.mapping.AutoValueMapper;
import com.example.mapstructtest.model.mapping.CarMapper;
import com.example.mapstructtest.model.mapping.ImmutableConstructableCarMapper;

public class MainActivity extends AppCompatActivity {

private TextView tv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.tv_text);
}

@Override
protected void onResume() {
super.onResume();
StringBuilder sb = new StringBuilder();
sb.append(manualMappingWithFluentSetter());
sb.append(withAutoValue());
sb.append(withAutoValueFluent());
sb.append(withAutoValueFluent());
// sb.append(withImmutable()); // Not yet for MapStruct 1.3
tv.setText(sb.toString());
}

String withImmutable() {
// MapStruct 1.3 does not support this immutable style contstructor.
ImmutableConstructableCar immutableConstructableCar = new ImmutableConstructableCar("Immutable Audi", 6, CarType.LARGE);
ImmutableConstructibleCarDto immutableCarDto = ImmutableConstructableCarMapper.INSTANCE.carToCarDto(immutableConstructableCar);
return getString("Immutable: ", immutableConstructableCar, immutableCarDto);
}

String manualMappingWithFluentSetter() {
Car car = new Car();
car.setConstructor("Audi");
car.setNumberOfSeats(5);
car.setType(CarType.LUXURY);
// Map the regular car
CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
// Then map it via fluent setter version
CarFluentSetter carFluentSetter = CarMapper.INSTANCE.toFluentSetterCar(carDto);
CarDto carDtoAgain = CarMapper.INSTANCE.toDto(carFluentSetter);
return getString("Car and car with fluent setter", car, carDto, carFluentSetter, carDtoAgain);
}

String withAutoValue() {
AutoValueCar.Builder builder = AutoValueCar.builder();
builder.setConstructor("Audi");
builder.setNumberOfSeats(5);
builder.setNumberOfAirbags(3);
builder.setType(CarType.LUXURY);
AutoValueCar car = builder.build();

AutoValueCarDto carDto = AutoValueMapper.INSTANCE.toDto(car);
AutoValueCar carAgain = AutoValueMapper.INSTANCE.toModel(carDto);
return getString("AutoValue mapping with MapStruct", car, carDto, carAgain);
}

String withAutoValueFluent() {
AutoValueFluentCar.Builder builder = AutoValueFluentCar.builder();
builder.constructor("Audi");
builder.numberOfSeats(5);
builder.type(CarType.LUXURY);
AutoValueFluentCar car = builder.build();
// MapStruct 1.3 does NOT work with fluent accessor style for getters, but does work with fluent setters
AutoValueFluentCarDto carDto = AutoValueFluentMapper.INSTANCE.toDto(car);
AutoValueFluentCar carAgain = AutoValueFluentMapper.INSTANCE.toModel(carDto);
return getString("AutoValue with fluent setter mapping", car, carDto, carAgain);
}

private String getString(String info, Object... objs) {
StringBuilder strb = new StringBuilder();
strb.append(info);
for (Object obj : objs) {
strb.append('\n');
strb.append(obj.toString());
}
strb.append('\n');
strb.append('\n');
return strb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.mapstructtest.model;

import com.google.auto.value.AutoValue;

@AutoValue
public abstract class AutoValueCar {
public abstract String getConstructor();
public abstract int getNumberOfSeats();
public abstract int getNumberOfAirbags();
public abstract CarType getType();

public static Builder builder() {
return new AutoValue_AutoValueCar.Builder();
}

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setConstructor(String value);
public abstract Builder setNumberOfSeats(int value);
public abstract Builder setNumberOfAirbags(int value);
public abstract Builder setType(CarType value);
public abstract AutoValueCar build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.mapstructtest.model;

import com.google.auto.value.AutoValue;

@AutoValue
public abstract class AutoValueCarDto {
public abstract String getConstructor();
public abstract int getSeatCount();
public abstract int getAirbagCount();
public abstract CarType getType();

public static Builder builder() {
return new AutoValue_AutoValueCarDto.Builder();
}

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setConstructor(String value);
public abstract Builder setSeatCount(int value);
public abstract Builder setAirbagCount(int value);
public abstract Builder setType(CarType value);
public abstract AutoValueCarDto build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.mapstructtest.model;

import android.support.annotation.Nullable;

import com.google.auto.value.AutoValue;

@AutoValue
public abstract class AutoValueFluentCar {
// MapStruct 1.3 does NOT work with fluent accessor style getters, hence the old-fashioned getX
@Nullable
public abstract String getConstructor();

public abstract int getNumberOfSeats();

@Nullable
public abstract CarType getType();

public static Builder builder() {
return new AutoValue_AutoValueFluentCar.Builder();
}

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder constructor(String value);

public abstract Builder numberOfSeats(int value);

public abstract Builder type(CarType value);

public abstract AutoValueFluentCar build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.example.mapstructtest.model;

import android.support.annotation.Nullable;

import com.google.auto.value.AutoValue;

@AutoValue
public abstract class AutoValueFluentCarDto {
// MapStruct 1.3 does NOT work with fluent accessor style getters, hence the old-fashioned getX
@Nullable
public abstract String getConstructor();

public abstract int getSeatCount();

@Nullable
public abstract CarType getType();

public static Builder builder() {
return new AutoValue_AutoValueFluentCarDto.Builder();
}

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder constructor(String value);

public abstract Builder seatCount(int value);

public abstract Builder type(CarType value);

public abstract AutoValueFluentCarDto build();
}
}
Loading