mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
Adding initial support for native mappers (work in progress)
This commit is contained in:
parent
069e4f3a80
commit
df25e12b0d
@ -15,6 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package de.moapa.maple;
|
package de.moapa.maple;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks an interface as mapper interface and activates the generation of a
|
||||||
|
* mapper implementation for that interface.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface Mapper {
|
public @interface Mapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the type of the mapper implementation to be generated.
|
||||||
|
* Currently supported values are {@code native} and {@code dozer}.
|
||||||
|
*
|
||||||
|
* @return The type of the mapper implementation to be generated.
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,12 @@ package de.moapa.maple.ap;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.AnnotationValue;
|
import javax.lang.model.element.AnnotationValue;
|
||||||
@ -28,6 +32,7 @@ import javax.lang.model.element.ExecutableElement;
|
|||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.element.VariableElement;
|
import javax.lang.model.element.VariableElement;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.ElementKindVisitor6;
|
import javax.lang.model.util.ElementKindVisitor6;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
@ -43,6 +48,7 @@ import de.moapa.maple.ap.model.Parameter;
|
|||||||
import de.moapa.maple.ap.model.Type;
|
import de.moapa.maple.ap.model.Type;
|
||||||
import de.moapa.maple.ap.writer.DozerModelWriter;
|
import de.moapa.maple.ap.writer.DozerModelWriter;
|
||||||
import de.moapa.maple.ap.writer.ModelWriter;
|
import de.moapa.maple.ap.writer.ModelWriter;
|
||||||
|
import de.moapa.maple.ap.writer.NativeModelWriter;
|
||||||
|
|
||||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||||
|
|
||||||
@ -50,12 +56,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
private final static String IMPLEMENTATION_SUFFIX = "Impl";
|
private final static String IMPLEMENTATION_SUFFIX = "Impl";
|
||||||
|
|
||||||
|
private final static String MAPPER_ANNOTATION = "de.moapa.maple.Mapper";
|
||||||
private final static String MAPPING_ANNOTATION = "de.moapa.maple.Mapping";
|
private final static String MAPPING_ANNOTATION = "de.moapa.maple.Mapping";
|
||||||
|
|
||||||
private final static String MAPPINGS_ANNOTATION = "de.moapa.maple.Mappings";
|
private final static String MAPPINGS_ANNOTATION = "de.moapa.maple.Mappings";
|
||||||
|
|
||||||
private final static String CONVERTER_TYPE = "de.moapa.maple.converter.Converter";
|
private final static String CONVERTER_TYPE = "de.moapa.maple.converter.Converter";
|
||||||
|
|
||||||
|
private final static String DEFAULT_MAPPER_TYPE = "dozer";
|
||||||
|
|
||||||
private final ProcessingEnvironment processingEnvironment;
|
private final ProcessingEnvironment processingEnvironment;
|
||||||
|
|
||||||
private final Types typeUtils;
|
private final Types typeUtils;
|
||||||
@ -90,13 +97,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
throw new RuntimeException( e );
|
throw new RuntimeException( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelWriter modelWriter = new DozerModelWriter();
|
ModelWriter modelWriter = model.getMapperType()
|
||||||
|
.equals( "native" ) ? new NativeModelWriter() : new DozerModelWriter();
|
||||||
modelWriter.writeModel( sourceFile, model );
|
modelWriter.writeModel( sourceFile, model );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mapper retrieveModel(TypeElement element) {
|
private Mapper retrieveModel(TypeElement element) {
|
||||||
|
|
||||||
return new Mapper(
|
return new Mapper(
|
||||||
|
retrieveMapperType( element ),
|
||||||
elementUtils.getPackageOf( element ).getQualifiedName().toString(),
|
elementUtils.getPackageOf( element ).getQualifiedName().toString(),
|
||||||
element.getSimpleName() + IMPLEMENTATION_SUFFIX,
|
element.getSimpleName() + IMPLEMENTATION_SUFFIX,
|
||||||
element.getSimpleName().toString(),
|
element.getSimpleName().toString(),
|
||||||
@ -104,6 +112,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String retrieveMapperType(TypeElement element) {
|
||||||
|
|
||||||
|
AnnotationMirror mapperAnnotation = getAnnotation( element, MAPPER_ANNOTATION );
|
||||||
|
String mapperType = getStringValue( mapperAnnotation, "value" );
|
||||||
|
|
||||||
|
return mapperType != null && !mapperType.isEmpty() ? mapperType : DEFAULT_MAPPER_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
private List<MapperMethod> retrieveMethods(TypeElement element) {
|
private List<MapperMethod> retrieveMethods(TypeElement element) {
|
||||||
|
|
||||||
List<MapperMethod> methods = new ArrayList<MapperMethod>();
|
List<MapperMethod> methods = new ArrayList<MapperMethod>();
|
||||||
@ -112,7 +128,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
|
|
||||||
Type returnType = retrieveReturnType( oneMethod );
|
Type returnType = retrieveReturnType( oneMethod );
|
||||||
Parameter parameter = retrieveParameter( oneMethod );
|
Parameter parameter = retrieveParameter( oneMethod );
|
||||||
List<Binding> bindings = retrieveBindings( oneMethod );
|
Map<String, Binding> bindings = retrieveBindings( oneMethod );
|
||||||
methods.add(
|
methods.add(
|
||||||
new MapperMethod(
|
new MapperMethod(
|
||||||
oneMethod.getSimpleName().toString(),
|
oneMethod.getSimpleName().toString(),
|
||||||
@ -126,9 +142,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Binding> retrieveBindings(ExecutableElement method) {
|
private Map<String, Binding> retrieveBindings(ExecutableElement method) {
|
||||||
|
|
||||||
List<Binding> bindings = new ArrayList<Binding>();
|
Map<String, Binding> bindings = new LinkedHashMap<String, Binding>();
|
||||||
|
|
||||||
|
retrieveDefaultBindings( method, bindings );
|
||||||
|
|
||||||
for ( AnnotationMirror annotationMirror : method.getAnnotationMirrors() ) {
|
for ( AnnotationMirror annotationMirror : method.getAnnotationMirrors() ) {
|
||||||
|
|
||||||
@ -137,76 +155,92 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
.accept( new NameDeterminationVisitor(), null );
|
.accept( new NameDeterminationVisitor(), null );
|
||||||
|
|
||||||
if ( MAPPING_ANNOTATION.equals( annotationName ) ) {
|
if ( MAPPING_ANNOTATION.equals( annotationName ) ) {
|
||||||
bindings.add( retrieveBinding( annotationMirror ) );
|
retrieveBinding( annotationMirror, bindings );
|
||||||
}
|
}
|
||||||
else if ( MAPPINGS_ANNOTATION.equals( annotationName ) ) {
|
else if ( MAPPINGS_ANNOTATION.equals( annotationName ) ) {
|
||||||
bindings.addAll( retrieveBindings( annotationMirror ) );
|
retrieveBindings( annotationMirror, bindings );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings;
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Binding> retrieveBindings(AnnotationMirror annotationMirror) {
|
private void retrieveDefaultBindings(ExecutableElement method, Map<String, Binding> bindings) {
|
||||||
|
|
||||||
List<Binding> bindings = new ArrayList<Binding>();
|
Element returnTypeElement = typeUtils.asElement( method.getReturnType() );
|
||||||
|
|
||||||
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
Set<String> writableTargetProperties = new LinkedHashSet<String>();
|
||||||
.entrySet() ) {
|
|
||||||
|
|
||||||
if ( oneAttribute.getKey().getSimpleName().contentEquals( "value" ) ) {
|
//collect writable properties of the target type
|
||||||
List<? extends AnnotationValue> values = oneAttribute.getValue()
|
for ( ExecutableElement oneMethod : methodsIn( returnTypeElement.getEnclosedElements() ) ) {
|
||||||
.accept( new AnnotationValueListRetrievingVisitor(), null );
|
if ( oneMethod.getSimpleName().toString().startsWith( "set" ) &&
|
||||||
|
oneMethod.getParameters().size() == 1 ) {
|
||||||
|
|
||||||
for ( AnnotationValue oneAnnotationValue : values ) {
|
writableTargetProperties.add( oneMethod.getSimpleName().toString().substring( 3 ) );
|
||||||
AnnotationMirror oneAnnotation = oneAnnotationValue.accept(
|
|
||||||
new AnnotationRetrievingVisitor(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
bindings.add( retrieveBinding( oneAnnotation ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings;
|
//collect readable properties of the source type
|
||||||
|
Element parameterElement = typeUtils.asElement( method.getParameters().get( 0 ).asType() );
|
||||||
|
|
||||||
|
Set<String> readableSourceProperties = new LinkedHashSet<String>();
|
||||||
|
|
||||||
|
for ( ExecutableElement oneMethod : methodsIn( parameterElement.getEnclosedElements() ) ) {
|
||||||
|
if ( oneMethod.getSimpleName().toString().startsWith( "get" ) &&
|
||||||
|
oneMethod.getParameters().isEmpty() &&
|
||||||
|
oneMethod.getReturnType().getKind() != TypeKind.VOID ) {
|
||||||
|
|
||||||
|
readableSourceProperties.add( oneMethod.getSimpleName().toString().substring( 3 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writableTargetProperties.retainAll( readableSourceProperties );
|
||||||
|
|
||||||
|
for ( String oneWritableProperty : writableTargetProperties ) {
|
||||||
|
bindings.put( oneWritableProperty, new Binding( oneWritableProperty, oneWritableProperty ) );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Binding retrieveBinding(AnnotationMirror annotationMirror) {
|
private void retrieveBindings(AnnotationMirror annotationMirror, Map<String, Binding> bindings) {
|
||||||
|
|
||||||
|
List<? extends AnnotationValue> values = getAnnotationValueListValue( annotationMirror, "value" );
|
||||||
|
|
||||||
|
for ( AnnotationValue oneAnnotationValue : values ) {
|
||||||
|
AnnotationMirror oneAnnotation = oneAnnotationValue.accept(
|
||||||
|
new AnnotationRetrievingVisitor(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
retrieveBinding( oneAnnotation, bindings );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retrieveBinding(AnnotationMirror annotationMirror, Map<String, Binding> bindings) {
|
||||||
|
|
||||||
|
String sourcePropertyName = getStringValue( annotationMirror, "source" );
|
||||||
|
String targetPropertyName = getStringValue( annotationMirror, "target" );
|
||||||
|
TypeMirror converterTypeMirror = getTypeMirrorValue( annotationMirror, "converter" );
|
||||||
|
|
||||||
String sourcePropertyName = null;
|
|
||||||
String targetPropertyName = null;
|
|
||||||
Type converterType = null;
|
Type converterType = null;
|
||||||
Type sourceType = null;
|
Type sourceType = null;
|
||||||
Type targetType = null;
|
Type targetType = null;
|
||||||
|
|
||||||
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
if ( converterTypeMirror != null ) {
|
||||||
.entrySet() ) {
|
converterType = getType( typeUtils.asElement( converterTypeMirror ) );
|
||||||
|
|
||||||
if ( oneAttribute.getKey().getSimpleName().contentEquals( "source" ) ) {
|
List<? extends TypeMirror> converterTypeParameters = getTypeParameters(
|
||||||
sourcePropertyName = oneAttribute.getValue().accept( new StringValueRetrievingVisitor(), null );
|
converterTypeMirror,
|
||||||
}
|
CONVERTER_TYPE
|
||||||
else if ( oneAttribute.getKey().getSimpleName().contentEquals( "target" ) ) {
|
);
|
||||||
targetPropertyName = oneAttribute.getValue().accept( new StringValueRetrievingVisitor(), null );
|
|
||||||
}
|
|
||||||
else if ( oneAttribute.getKey().getSimpleName().contentEquals( "converter" ) ) {
|
|
||||||
TypeMirror converterTypeMirror = oneAttribute.getValue()
|
|
||||||
.accept(
|
|
||||||
new TypeRetrievingVisitor(), null
|
|
||||||
);
|
|
||||||
|
|
||||||
converterType = getType( typeUtils.asElement( converterTypeMirror ) );
|
sourceType = getType( typeUtils.asElement( converterTypeParameters.get( 0 ) ) );
|
||||||
|
targetType = getType( typeUtils.asElement( converterTypeParameters.get( 1 ) ) );
|
||||||
List<? extends TypeMirror> converterTypeParameters = getTypeParameters(
|
|
||||||
converterTypeMirror,
|
|
||||||
CONVERTER_TYPE
|
|
||||||
);
|
|
||||||
|
|
||||||
sourceType = getType( typeUtils.asElement( converterTypeParameters.get( 0 ) ) );
|
|
||||||
targetType = getType( typeUtils.asElement( converterTypeParameters.get( 1 ) ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Binding( sourceType, sourcePropertyName, targetType, targetPropertyName, converterType );
|
bindings.put(
|
||||||
|
sourcePropertyName,
|
||||||
|
new Binding( sourceType, sourcePropertyName, targetType, targetPropertyName, converterType )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type getType(Element sourceTypeElement) {
|
private Type getType(Element sourceTypeElement) {
|
||||||
@ -261,6 +295,60 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AnnotationMirror getAnnotation(TypeElement element, String annotationName) {
|
||||||
|
|
||||||
|
for ( AnnotationMirror annotationMirror : element.getAnnotationMirrors() ) {
|
||||||
|
|
||||||
|
if ( annotationName.equals(
|
||||||
|
annotationMirror.getAnnotationType().asElement().accept( new NameDeterminationVisitor(), null )
|
||||||
|
) ) {
|
||||||
|
|
||||||
|
return annotationMirror;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStringValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
|
.entrySet() ) {
|
||||||
|
|
||||||
|
if ( oneAttribute.getKey().getSimpleName().contentEquals( attributeName ) ) {
|
||||||
|
return oneAttribute.getValue().accept( new StringValueRetrievingVisitor(), null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeMirror getTypeMirrorValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
|
.entrySet() ) {
|
||||||
|
|
||||||
|
if ( oneAttribute.getKey().getSimpleName().contentEquals( attributeName ) ) {
|
||||||
|
return oneAttribute.getValue().accept( new TypeRetrievingVisitor(), null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<? extends AnnotationValue> getAnnotationValueListValue(AnnotationMirror annotationMirror, String attributeName) {
|
||||||
|
|
||||||
|
for ( Entry<? extends ExecutableElement, ? extends AnnotationValue> oneAttribute : annotationMirror.getElementValues()
|
||||||
|
.entrySet() ) {
|
||||||
|
|
||||||
|
if ( oneAttribute.getKey().getSimpleName().contentEquals( "value" ) ) {
|
||||||
|
return oneAttribute.getValue().accept( new AnnotationValueListRetrievingVisitor(), null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static class TypeParameterDeterminationVisitor extends TypeKindVisitor6<List<? extends TypeMirror>, Void> {
|
private static class TypeParameterDeterminationVisitor extends TypeKindVisitor6<List<? extends TypeMirror>, Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,15 +18,15 @@ package de.moapa.maple.ap.model;
|
|||||||
public class Binding {
|
public class Binding {
|
||||||
|
|
||||||
private final Type sourceType;
|
private final Type sourceType;
|
||||||
|
|
||||||
private final String sourceProperty;
|
private final String sourceProperty;
|
||||||
|
|
||||||
private final Type targetType;
|
private final Type targetType;
|
||||||
|
|
||||||
private final String targetProperty;
|
private final String targetProperty;
|
||||||
|
|
||||||
private final Type converterType;
|
private final Type converterType;
|
||||||
|
|
||||||
|
public Binding(String sourceProperty, String targetProperty) {
|
||||||
|
this( null, sourceProperty, null, targetProperty, null );
|
||||||
|
}
|
||||||
|
|
||||||
public Binding(Type sourceType, String sourceProperty, Type targetType, String targetProperty, Type converterType) {
|
public Binding(Type sourceType, String sourceProperty, Type targetType, String targetProperty, Type converterType) {
|
||||||
|
|
||||||
this.sourceType = sourceType;
|
this.sourceType = sourceType;
|
||||||
@ -55,4 +55,8 @@ public class Binding {
|
|||||||
public Type getConverterType() {
|
public Type getConverterType() {
|
||||||
return converterType;
|
return converterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDefault() {
|
||||||
|
return !sourceProperty.equals( targetProperty ) || ( sourceType != null && !sourceType.equals( targetType ) ) ? false : true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,15 @@ import java.util.List;
|
|||||||
|
|
||||||
public class Mapper {
|
public class Mapper {
|
||||||
|
|
||||||
|
private final String mapperType;
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
|
|
||||||
private final String implementationType;
|
private final String implementationType;
|
||||||
|
|
||||||
private final String interfaceType;
|
private final String interfaceType;
|
||||||
|
|
||||||
private final List<MapperMethod> mapperMethods;
|
private final List<MapperMethod> mapperMethods;
|
||||||
|
|
||||||
private final List<Converter> converters;
|
private final List<Converter> converters;
|
||||||
|
|
||||||
public Mapper(String packageName, String implementationType, String interfaceType, List<MapperMethod> mapperMethods) {
|
public Mapper(String mapperType, String packageName, String implementationType, String interfaceType, List<MapperMethod> mapperMethods) {
|
||||||
|
this.mapperType = mapperType;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.implementationType = implementationType;
|
this.implementationType = implementationType;
|
||||||
this.interfaceType = interfaceType;
|
this.interfaceType = interfaceType;
|
||||||
@ -43,7 +41,7 @@ public class Mapper {
|
|||||||
List<Converter> converters = new ArrayList<Converter>();
|
List<Converter> converters = new ArrayList<Converter>();
|
||||||
|
|
||||||
for ( MapperMethod oneMapperMethod : mapperMethods ) {
|
for ( MapperMethod oneMapperMethod : mapperMethods ) {
|
||||||
for ( Binding oneBinding : oneMapperMethod.getBindings() ) {
|
for ( Binding oneBinding : oneMapperMethod.getBindings().values() ) {
|
||||||
if ( oneBinding.getConverterType() != null ) {
|
if ( oneBinding.getConverterType() != null ) {
|
||||||
converters.add(
|
converters.add(
|
||||||
new Converter(
|
new Converter(
|
||||||
@ -59,6 +57,10 @@ public class Mapper {
|
|||||||
return converters;
|
return converters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMapperType() {
|
||||||
|
return mapperType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return packageName;
|
return packageName;
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,21 @@
|
|||||||
*/
|
*/
|
||||||
package de.moapa.maple.ap.model;
|
package de.moapa.maple.ap.model;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
public class MapperMethod {
|
public class MapperMethod {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Type returnType;
|
private final Type returnType;
|
||||||
private final Parameter parameter;
|
private final Parameter parameter;
|
||||||
private final List<Binding> bindings;
|
|
||||||
|
|
||||||
public MapperMethod(String name, Type returnType, Parameter parameter, List<Binding> bindings) {
|
/**
|
||||||
|
* Bindings for the properties of this method's converted object. Keyed by
|
||||||
|
* property name of the source type.
|
||||||
|
*/
|
||||||
|
private final Map<String, Binding> bindings;
|
||||||
|
|
||||||
|
public MapperMethod(String name, Type returnType, Parameter parameter, Map<String, Binding> bindings) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.parameter = parameter;
|
this.parameter = parameter;
|
||||||
@ -43,7 +48,17 @@ public class MapperMethod {
|
|||||||
return parameter;
|
return parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Binding> getBindings() {
|
public Map<String, Binding> getBindings() {
|
||||||
return bindings;
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getNonDefaultBindingExisting() {
|
||||||
|
for ( Binding oneBinding : bindings.values() ) {
|
||||||
|
if ( !oneBinding.isDefault() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,5 +55,4 @@ public class DozerModelWriter implements ModelWriter {
|
|||||||
throw new RuntimeException( e );
|
throw new RuntimeException( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package de.moapa.maple.ap.writer;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
|
import de.moapa.maple.ap.model.Mapper;
|
||||||
|
import freemarker.template.Configuration;
|
||||||
|
import freemarker.template.DefaultObjectWrapper;
|
||||||
|
import freemarker.template.Template;
|
||||||
|
|
||||||
|
public class NativeModelWriter implements ModelWriter {
|
||||||
|
|
||||||
|
private final static String TEMPLATE_NAME = "native-mapper-implementation.ftl";
|
||||||
|
|
||||||
|
private static final Configuration configuration;
|
||||||
|
|
||||||
|
static {
|
||||||
|
|
||||||
|
configuration = new Configuration();
|
||||||
|
configuration.setClassForTemplateLoading( NativeModelWriter.class, "/" );
|
||||||
|
configuration.setObjectWrapper( new DefaultObjectWrapper() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeModel(JavaFileObject sourceFile, Mapper model) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedWriter writer = new BufferedWriter( sourceFile.openWriter() );
|
||||||
|
|
||||||
|
Template template = configuration.getTemplate( TEMPLATE_NAME );
|
||||||
|
template.process( model, writer );
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch ( RuntimeException e ) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,11 +35,11 @@ public class ${implementationType} implements ${interfaceType} {
|
|||||||
BeanMappingBuilder builder = null;
|
BeanMappingBuilder builder = null;
|
||||||
|
|
||||||
<#list mapperMethods as oneMethod>
|
<#list mapperMethods as oneMethod>
|
||||||
<#if oneMethod.bindings?has_content>
|
<#if oneMethod.nonDefaultBindingExisting>
|
||||||
builder = new BeanMappingBuilder() {
|
builder = new BeanMappingBuilder() {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
mapping( ${oneMethod.parameter.type.name}.class, ${oneMethod.returnType.name}.class )
|
mapping( ${oneMethod.parameter.type.name}.class, ${oneMethod.returnType.name}.class )
|
||||||
<#list oneMethod.bindings as oneBinding>
|
<#list oneMethod.bindings?values as oneBinding>
|
||||||
.fields( "${oneBinding.sourceProperty}", "${oneBinding.targetProperty}"<#if oneBinding.converterType??>, customConverter( ${oneBinding.converterType.name}DozerAdapter.class )</#if> )
|
.fields( "${oneBinding.sourceProperty}", "${oneBinding.targetProperty}"<#if oneBinding.converterType??>, customConverter( ${oneBinding.converterType.name}DozerAdapter.class )</#if> )
|
||||||
</#list>
|
</#list>
|
||||||
;
|
;
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
package ${packageName};
|
||||||
|
|
||||||
|
public class ${implementationType} implements ${interfaceType} {
|
||||||
|
|
||||||
|
<#list mapperMethods as oneMethod>
|
||||||
|
public ${oneMethod.returnType.name} ${oneMethod.name}(${oneMethod.parameter.type.name} ${oneMethod.parameter.name}) {
|
||||||
|
|
||||||
|
${oneMethod.returnType.name} convertedObject = new ${oneMethod.returnType.name}();
|
||||||
|
|
||||||
|
<#list oneMethod.bindings?values as oneBinding>
|
||||||
|
<#if oneBinding.converterType??>
|
||||||
|
convertedObject.set${oneBinding.targetProperty?cap_first}( new ${oneBinding.converterType.name}().from( ${oneMethod.parameter.name}.get${oneBinding.sourceProperty?cap_first}() ) );
|
||||||
|
<#else>
|
||||||
|
convertedObject.set${oneBinding.targetProperty?cap_first}( ${oneMethod.parameter.name}.get${oneBinding.sourceProperty?cap_first}() );
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
|
||||||
|
return convertedObject;
|
||||||
|
}
|
||||||
|
</#list>
|
||||||
|
}
|
@ -16,68 +16,24 @@
|
|||||||
package de.moapa.maple.ap.test;
|
package de.moapa.maple.ap.test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.tools.DiagnosticCollector;
|
import javax.tools.DiagnosticCollector;
|
||||||
import javax.tools.JavaCompiler;
|
|
||||||
import javax.tools.JavaCompiler.CompilationTask;
|
|
||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
import javax.tools.StandardJavaFileManager;
|
|
||||||
import javax.tools.StandardLocation;
|
|
||||||
import javax.tools.ToolProvider;
|
|
||||||
|
|
||||||
import de.moapa.maple.ap.MappingProcessor;
|
|
||||||
import de.moapa.maple.ap.test.model.Car;
|
import de.moapa.maple.ap.test.model.Car;
|
||||||
import de.moapa.maple.ap.test.model.CarDto;
|
import de.moapa.maple.ap.test.model.CarDto;
|
||||||
import de.moapa.maple.ap.test.model.CarMapper;
|
import de.moapa.maple.ap.test.model.CarMapper;
|
||||||
import de.moapa.maple.ap.test.model.IntToStringConverter;
|
import de.moapa.maple.ap.test.model.IntToStringConverter;
|
||||||
import org.testng.annotations.BeforeClass;
|
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import static org.fest.assertions.Assertions.assertThat;
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
public class CarMapperTest {
|
public class CarMapperTest extends MapperTestBase {
|
||||||
|
|
||||||
private DiagnosticCollector<JavaFileObject> diagnostics;
|
private DiagnosticCollector<JavaFileObject> diagnostics;
|
||||||
private JavaCompiler compiler;
|
|
||||||
|
|
||||||
private String sourceDir;
|
public CarMapperTest() {
|
||||||
private String classOutputDir;
|
super( "maple.jar", "dozer.jar", "slf4j-api.jar", "slf4j-jdk14.jar" );
|
||||||
private String sourceOutputDir;
|
|
||||||
private List<File> classPath;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public void setup() throws Exception {
|
|
||||||
|
|
||||||
compiler = ToolProvider.getSystemJavaCompiler();
|
|
||||||
|
|
||||||
String basePath = getBasePath();
|
|
||||||
|
|
||||||
sourceDir = basePath + "/src/test/java";
|
|
||||||
classOutputDir = basePath + "/target/compilation-tests/classes";
|
|
||||||
sourceOutputDir = basePath + "/target/compilation-tests/generated-sources/mapping";
|
|
||||||
|
|
||||||
String testDependenciesDir = basePath + "/target/test-dependencies/";
|
|
||||||
classPath = Arrays.asList(
|
|
||||||
new File( testDependenciesDir, "maple.jar" ),
|
|
||||||
new File( testDependenciesDir, "dozer.jar" ),
|
|
||||||
new File( testDependenciesDir, "slf4j-api.jar" ),
|
|
||||||
new File( testDependenciesDir, "slf4j-jdk14.jar" )
|
|
||||||
);
|
|
||||||
|
|
||||||
createOutputDirs();
|
|
||||||
|
|
||||||
Thread.currentThread().setContextClassLoader(
|
|
||||||
new URLClassLoader(
|
|
||||||
new URL[] { new File( classOutputDir ).toURI().toURL() },
|
|
||||||
Thread.currentThread().getContextClassLoader()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeMethod
|
@BeforeMethod
|
||||||
@ -167,86 +123,4 @@ public class CarMapperTest {
|
|||||||
assertThat( car ).isNotNull();
|
assertThat( car ).isNotNull();
|
||||||
assertThat( car.getYearOfManufacture() ).isEqualTo( 1980 );
|
assertThat( car.getYearOfManufacture() ).isEqualTo( 1980 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private File[] getSourceFiles(Class<?>... clazz) {
|
|
||||||
|
|
||||||
File[] sourceFiles = new File[clazz.length];
|
|
||||||
|
|
||||||
for ( int i = 0; i < clazz.length; i++ ) {
|
|
||||||
|
|
||||||
sourceFiles[i] = new File(
|
|
||||||
sourceDir +
|
|
||||||
File.separator +
|
|
||||||
clazz[i].getName().replace( ".", File.separator ) +
|
|
||||||
".java"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return sourceFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean compile(DiagnosticCollector<JavaFileObject> diagnostics, File... sourceFiles) {
|
|
||||||
|
|
||||||
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
|
|
||||||
|
|
||||||
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects( sourceFiles );
|
|
||||||
|
|
||||||
try {
|
|
||||||
fileManager.setLocation( StandardLocation.CLASS_PATH, classPath );
|
|
||||||
fileManager.setLocation( StandardLocation.CLASS_OUTPUT, Arrays.asList( new File( classOutputDir ) ) );
|
|
||||||
fileManager.setLocation( StandardLocation.SOURCE_OUTPUT, Arrays.asList( new File( sourceOutputDir ) ) );
|
|
||||||
}
|
|
||||||
catch ( IOException e ) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
CompilationTask task = compiler.getTask(
|
|
||||||
null,
|
|
||||||
fileManager,
|
|
||||||
diagnostics,
|
|
||||||
Collections.<String>emptyList(),
|
|
||||||
null,
|
|
||||||
compilationUnits
|
|
||||||
);
|
|
||||||
task.setProcessors( Arrays.asList( new MappingProcessor() ) );
|
|
||||||
|
|
||||||
return task.call();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getBasePath() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
return new File( "." ).getCanonicalPath();
|
|
||||||
}
|
|
||||||
catch ( IOException e ) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createOutputDirs() {
|
|
||||||
|
|
||||||
File directory = new File( classOutputDir );
|
|
||||||
deleteDirectory( directory );
|
|
||||||
directory.mkdirs();
|
|
||||||
|
|
||||||
directory = new File( sourceOutputDir );
|
|
||||||
deleteDirectory( directory );
|
|
||||||
directory.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteDirectory(File path) {
|
|
||||||
if ( path.exists() ) {
|
|
||||||
File[] files = path.listFiles();
|
|
||||||
for ( int i = 0; i < files.length; i++ ) {
|
|
||||||
if ( files[i].isDirectory() ) {
|
|
||||||
deleteDirectory( files[i] );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
files[i].delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
path.delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package de.moapa.maple.ap.test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.tools.DiagnosticCollector;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaCompiler.CompilationTask;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
import de.moapa.maple.ap.MappingProcessor;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
|
||||||
|
public abstract class MapperTestBase {
|
||||||
|
|
||||||
|
private JavaCompiler compiler;
|
||||||
|
private String sourceDir;
|
||||||
|
private String classOutputDir;
|
||||||
|
private String sourceOutputDir;
|
||||||
|
private List<File> classPath;
|
||||||
|
private List<String> libraries;
|
||||||
|
|
||||||
|
public MapperTestBase(String... libraries) {
|
||||||
|
this.libraries = Arrays.asList( libraries );
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public void setup() throws Exception {
|
||||||
|
|
||||||
|
compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
|
||||||
|
String basePath = getBasePath();
|
||||||
|
|
||||||
|
sourceDir = basePath + "/src/test/java";
|
||||||
|
classOutputDir = basePath + "/target/compilation-tests/classes";
|
||||||
|
sourceOutputDir = basePath + "/target/compilation-tests/generated-sources/mapping";
|
||||||
|
|
||||||
|
String testDependenciesDir = basePath + "/target/test-dependencies/";
|
||||||
|
|
||||||
|
classPath = new ArrayList<File>();
|
||||||
|
for ( String oneLibrary : libraries ) {
|
||||||
|
classPath.add( new File( testDependenciesDir, oneLibrary ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
createOutputDirs();
|
||||||
|
|
||||||
|
Thread.currentThread().setContextClassLoader(
|
||||||
|
new URLClassLoader(
|
||||||
|
new URL[] { new File( classOutputDir ).toURI().toURL() },
|
||||||
|
Thread.currentThread().getContextClassLoader()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File[] getSourceFiles(Class<?>... clazz) {
|
||||||
|
|
||||||
|
File[] sourceFiles = new File[clazz.length];
|
||||||
|
|
||||||
|
for ( int i = 0; i < clazz.length; i++ ) {
|
||||||
|
|
||||||
|
sourceFiles[i] = new File(
|
||||||
|
sourceDir +
|
||||||
|
File.separator +
|
||||||
|
clazz[i].getName().replace( ".", File.separator ) +
|
||||||
|
".java"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return sourceFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean compile(DiagnosticCollector<JavaFileObject> diagnostics, File... sourceFiles) {
|
||||||
|
|
||||||
|
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
|
||||||
|
|
||||||
|
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects( sourceFiles );
|
||||||
|
|
||||||
|
try {
|
||||||
|
fileManager.setLocation( StandardLocation.CLASS_PATH, classPath );
|
||||||
|
fileManager.setLocation( StandardLocation.CLASS_OUTPUT, Arrays.asList( new File( classOutputDir ) ) );
|
||||||
|
fileManager.setLocation( StandardLocation.SOURCE_OUTPUT, Arrays.asList( new File( sourceOutputDir ) ) );
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilationTask task = compiler.getTask(
|
||||||
|
null,
|
||||||
|
fileManager,
|
||||||
|
diagnostics,
|
||||||
|
Collections.<String>emptyList(),
|
||||||
|
null,
|
||||||
|
compilationUnits
|
||||||
|
);
|
||||||
|
task.setProcessors( Arrays.asList( new MappingProcessor() ) );
|
||||||
|
|
||||||
|
return task.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getBasePath() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new File( "." ).getCanonicalPath();
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createOutputDirs() {
|
||||||
|
|
||||||
|
File directory = new File( classOutputDir );
|
||||||
|
deleteDirectory( directory );
|
||||||
|
directory.mkdirs();
|
||||||
|
|
||||||
|
directory = new File( sourceOutputDir );
|
||||||
|
deleteDirectory( directory );
|
||||||
|
directory.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteDirectory(File path) {
|
||||||
|
if ( path.exists() ) {
|
||||||
|
File[] files = path.listFiles();
|
||||||
|
for ( int i = 0; i < files.length; i++ ) {
|
||||||
|
if ( files[i].isDirectory() ) {
|
||||||
|
deleteDirectory( files[i] );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
files[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package de.moapa.maple.ap.test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import javax.tools.DiagnosticCollector;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
|
import de.moapa.maple.ap.test.model.Car;
|
||||||
|
import de.moapa.maple.ap.test.model.CarDto;
|
||||||
|
import de.moapa.maple.ap.test.model.IntToStringConverter;
|
||||||
|
import de.moapa.maple.ap.test.model.NativeCarMapper;
|
||||||
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
public class NativeCarMapperTest extends MapperTestBase {
|
||||||
|
|
||||||
|
private DiagnosticCollector<JavaFileObject> diagnostics;
|
||||||
|
|
||||||
|
public NativeCarMapperTest() {
|
||||||
|
super( "maple.jar" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeMethod
|
||||||
|
public void generateMapperImplementation() {
|
||||||
|
|
||||||
|
diagnostics = new DiagnosticCollector<JavaFileObject>();
|
||||||
|
File[] sourceFiles = getSourceFiles(
|
||||||
|
Car.class,
|
||||||
|
CarDto.class,
|
||||||
|
NativeCarMapper.class,
|
||||||
|
IntToStringConverter.class
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean compilationSuccessful = compile( diagnostics, sourceFiles );
|
||||||
|
|
||||||
|
assertThat( compilationSuccessful ).describedAs( "Compilation failed: " + diagnostics.getDiagnostics() )
|
||||||
|
.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldProvideMapperInstance() throws Exception {
|
||||||
|
|
||||||
|
assertThat( NativeCarMapper.INSTANCE ).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapAttributeByName() {
|
||||||
|
|
||||||
|
//given
|
||||||
|
Car car = new Car( "Morris", 2, 1980 );
|
||||||
|
|
||||||
|
//when
|
||||||
|
CarDto carDto = NativeCarMapper.INSTANCE.carToCarDto( car );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( carDto ).isNotNull();
|
||||||
|
assertThat( carDto.getMake() ).isEqualTo( car.getMake() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldMapAttributeWithCustomMapping() {
|
||||||
|
|
||||||
|
//given
|
||||||
|
Car car = new Car( "Morris", 2, 1980 );
|
||||||
|
|
||||||
|
//when
|
||||||
|
CarDto carDto = NativeCarMapper.INSTANCE.carToCarDto( car );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( carDto ).isNotNull();
|
||||||
|
assertThat( carDto.getSeatCount() ).isEqualTo( car.getNumberOfSeats() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
|
public void shouldConsiderCustomMappingForReverseMapping() {
|
||||||
|
|
||||||
|
//given
|
||||||
|
CarDto carDto = new CarDto( "Morris", 2, "1980" );
|
||||||
|
|
||||||
|
//when
|
||||||
|
Car car = NativeCarMapper.INSTANCE.carDtoToCar( carDto );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( car ).isNotNull();
|
||||||
|
assertThat( car.getNumberOfSeats() ).isEqualTo( carDto.getSeatCount() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldApplyConverter() {
|
||||||
|
|
||||||
|
//given
|
||||||
|
Car car = new Car( "Morris", 2, 1980 );
|
||||||
|
|
||||||
|
//when
|
||||||
|
CarDto carDto = NativeCarMapper.INSTANCE.carToCarDto( car );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( carDto ).isNotNull();
|
||||||
|
assertThat( carDto.getManufacturingYear() ).isEqualTo( "1980" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
|
public void shouldApplyConverterForReverseMapping() {
|
||||||
|
|
||||||
|
//given
|
||||||
|
CarDto carDto = new CarDto( "Morris", 2, "1980" );
|
||||||
|
|
||||||
|
//when
|
||||||
|
Car car = NativeCarMapper.INSTANCE.carDtoToCar( carDto );
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertThat( car ).isNotNull();
|
||||||
|
assertThat( car.getYearOfManufacture() ).isEqualTo( 1980 );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package de.moapa.maple.ap.test.model;
|
||||||
|
|
||||||
|
import de.moapa.maple.Mapper;
|
||||||
|
import de.moapa.maple.Mappers;
|
||||||
|
import de.moapa.maple.Mapping;
|
||||||
|
import de.moapa.maple.Mappings;
|
||||||
|
|
||||||
|
@Mapper("native")
|
||||||
|
public interface NativeCarMapper {
|
||||||
|
|
||||||
|
NativeCarMapper INSTANCE = Mappers.getMapper( NativeCarMapper.class );
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "numberOfSeats", target = "seatCount"),
|
||||||
|
@Mapping(source = "yearOfManufacture", target = "manufacturingYear", converter = IntToStringConverter.class)
|
||||||
|
})
|
||||||
|
CarDto carToCarDto(Car car);
|
||||||
|
|
||||||
|
Car carDtoToCar(CarDto carDto);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user