#1 Adding string conversions for native data types

This commit is contained in:
Gunnar Morling 2013-05-18 12:06:17 +02:00
parent 4c462eb9a0
commit 74e673945f
11 changed files with 705 additions and 9 deletions

View File

@ -53,6 +53,7 @@ import org.mapstruct.ap.model.source.Mapping;
import org.mapstruct.ap.model.source.Method;
import org.mapstruct.ap.model.source.Parameter;
import org.mapstruct.ap.util.Filters;
import org.mapstruct.ap.util.Strings;
import org.mapstruct.ap.util.TypeUtil;
import org.mapstruct.ap.writer.ModelWriter;
@ -246,11 +247,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
}
private String getAccessor(String name) {
return "get" + capitalize( name ) + "()";
}
private String capitalize(String name) {
return name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
return "get" + Strings.capitalize( name ) + "()";
}
private MappingMethod getElementMappingMethod(Iterable<Method> methods, Method method) {

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.conversion;
import org.mapstruct.ap.model.Type;
public class IntStringConversion implements Conversion {
public class CharToStringConversion implements Conversion {
@Override
public String to(String sourcePropertyAccessor, Type type) {
@ -29,6 +29,6 @@ public class IntStringConversion implements Conversion {
@Override
public String from(String targetPropertyAccessor, Type type) {
return "Integer.parseInt( " + targetPropertyAccessor + " )";
return targetPropertyAccessor + ".charAt( 0 )";
}
}

View File

@ -0,0 +1,34 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.conversion;
import org.mapstruct.ap.model.Type;
public class CharWrapperToStringConversion implements Conversion {
@Override
public String to(String sourcePropertyAccessor, Type type) {
return sourcePropertyAccessor + ".toString()";
}
@Override
public String from(String targetPropertyAccessor, Type type) {
return targetPropertyAccessor + ".charAt( 0 )";
}
}

View File

@ -119,8 +119,23 @@ public class Conversions {
registerNumberConversion( double.class, Double.class );
register( int.class, String.class, new IntStringConversion() );
register( Integer.class, String.class, new IntegerStringConversion() );
registerToStringConversion( byte.class );
registerToStringConversion( Byte.class );
registerToStringConversion( short.class );
registerToStringConversion( Short.class );
registerToStringConversion( int.class );
registerToStringConversion( Integer.class );
registerToStringConversion( long.class );
registerToStringConversion( Long.class );
registerToStringConversion( float.class );
registerToStringConversion( Float.class );
registerToStringConversion( double.class );
registerToStringConversion( Double.class );
registerToStringConversion( boolean.class );
registerToStringConversion( Boolean.class );
register( char.class, String.class, new CharToStringConversion() );
register( Character.class, String.class, new CharWrapperToStringConversion() );
register( Enum.class, String.class, new EnumStringConversion() );
}
@ -139,6 +154,15 @@ public class Conversions {
}
}
private void registerToStringConversion(Class<?> sourceType) {
if ( sourceType.isPrimitive() ) {
register( sourceType, String.class, new PrimitiveToStringConversion( sourceType ) );
}
else {
register( sourceType, String.class, new WrapperToStringConversion( sourceType ) );
}
}
private void register(Class<?> sourceType, Class<?> targetType, Conversion conversion) {
conversions.put( Key.forClasses( sourceType, targetType ), conversion );
conversions.put( Key.forClasses( targetType, sourceType ), reverse( conversion ) );

View File

@ -0,0 +1,66 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.conversion;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.mapstruct.ap.model.Type;
import org.mapstruct.ap.util.Strings;
public class PrimitiveToStringConversion implements Conversion {
private final static Map<Class<?>, Class<?>> primitiveToWrapperTypes;
static {
Map<Class<?>, Class<?>> tmp = new HashMap<Class<?>, Class<?>>();
tmp.put( byte.class, Byte.class );
tmp.put( short.class, Short.class );
tmp.put( int.class, Integer.class );
tmp.put( long.class, Long.class );
tmp.put( float.class, Float.class );
tmp.put( double.class, Double.class );
tmp.put( boolean.class, Boolean.class );
primitiveToWrapperTypes = Collections.unmodifiableMap( tmp );
}
private final Class<?> sourceType;
private final Class<?> wrapperType;
public PrimitiveToStringConversion(Class<?> sourceType) {
if ( !sourceType.isPrimitive() ) {
throw new IllegalArgumentException( sourceType + " is no primitive type." );
}
this.sourceType = sourceType;
this.wrapperType = primitiveToWrapperTypes.get( sourceType );
}
@Override
public String to(String sourcePropertyAccessor, Type type) {
return "String.valueOf( " + sourcePropertyAccessor + " )";
}
@Override
public String from(String targetPropertyAccessor, Type type) {
return wrapperType.getSimpleName() + ".parse" + Strings.capitalize( sourceType.getSimpleName() ) + "( " + targetPropertyAccessor + " )";
}
}

View File

@ -0,0 +1,66 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.conversion;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.mapstruct.ap.model.Type;
import org.mapstruct.ap.util.Strings;
public class WrapperToStringConversion implements Conversion {
private final static Map<Class<?>, Class<?>> wrapperToPrimitiveTypes;
static {
Map<Class<?>, Class<?>> tmp = new HashMap<Class<?>, Class<?>>();
tmp.put( Byte.class, byte.class );
tmp.put( Short.class, short.class );
tmp.put( Integer.class, int.class );
tmp.put( Long.class, long.class );
tmp.put( Float.class, float.class );
tmp.put( Double.class, double.class );
tmp.put( Boolean.class, boolean.class );
wrapperToPrimitiveTypes = Collections.unmodifiableMap( tmp );
}
private final Class<?> sourceType;
private final Class<?> primitiveType;
public WrapperToStringConversion(Class<?> sourceType) {
if ( sourceType.isPrimitive() ) {
throw new IllegalArgumentException( sourceType + " is no wrapper type." );
}
this.sourceType = sourceType;
this.primitiveType = wrapperToPrimitiveTypes.get( sourceType );
}
@Override
public String to(String sourcePropertyAccessor, Type type) {
return "String.valueOf( " + sourcePropertyAccessor + " )";
}
@Override
public String from(String targetPropertyAccessor, Type type) {
return sourceType.getSimpleName() + ".parse" + Strings.capitalize( primitiveType.getSimpleName() ) + "( " + targetPropertyAccessor + " )";
}
}

View File

@ -0,0 +1,27 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.util;
public class Strings {
public static String capitalize(String name) {
return name == null ? null : name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
}
}

View File

@ -0,0 +1,167 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.test.conversion.string;
public class Source {
private byte b;
private Byte bb;
private short s;
private Short ss;
private int i;
private Integer ii;
private long l;
private Long ll;
private float f;
private Float ff;
private double d;
private Double dd;
private boolean bool;
private Boolean boolBool;
private char c;
private Character cc;
public byte getB() {
return b;
}
public void setB(byte b) {
this.b = b;
}
public Byte getBb() {
return bb;
}
public void setBb(Byte bb) {
this.bb = bb;
}
public short getS() {
return s;
}
public void setS(short s) {
this.s = s;
}
public Short getSs() {
return ss;
}
public void setSs(Short ss) {
this.ss = ss;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public Integer getIi() {
return ii;
}
public void setIi(Integer ii) {
this.ii = ii;
}
public long getL() {
return l;
}
public void setL(long l) {
this.l = l;
}
public Long getLl() {
return ll;
}
public void setLl(Long ll) {
this.ll = ll;
}
public float getF() {
return f;
}
public void setF(float f) {
this.f = f;
}
public Float getFf() {
return ff;
}
public void setFf(Float ff) {
this.ff = ff;
}
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
public Double getDd() {
return dd;
}
public void setDd(Double dd) {
this.dd = dd;
}
public boolean getBool() {
return bool;
}
public void setBool(boolean bool) {
this.bool = bool;
}
public Boolean getBoolBool() {
return boolBool;
}
public void setBoolBool(Boolean boolBool) {
this.boolBool = boolBool;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public Character getCc() {
return cc;
}
public void setCc(Character cc) {
this.cc = cc;
}
}

View File

@ -0,0 +1,32 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.test.conversion.string;
import org.mapstruct.Mapper;
import org.mapstruct.Mappers;
@Mapper
public interface SourceTargetMapper {
public static SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
Target sourceToTarget(Source source);
Source targetToSource(Target target);
}

View File

@ -0,0 +1,115 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.test.conversion.string;
import org.mapstruct.ap.testutil.MapperTestBase;
import org.mapstruct.ap.testutil.WithClasses;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
@WithClasses({
Source.class,
Target.class,
SourceTargetMapper.class
})
public class StringConversionTest extends MapperTestBase {
@Test
public void shouldApplyStringConversions() {
Source source = new Source();
source.setB( (byte) 1 );
source.setBb( (byte) 2 );
source.setS( (short) 3 );
source.setSs( (short) 4 );
source.setI( 5 );
source.setIi( 6 );
source.setL( 7L );
source.setLl( 8L );
source.setF( 9f );
source.setFf( 10f );
source.setD( 11d );
source.setDd( 12d );
source.setBool( true );
source.setBoolBool( Boolean.TRUE );
source.setC( 'G' );
source.setCc( 'H' );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getB() ).isEqualTo( "1" );
assertThat( target.getBb() ).isEqualTo( "2" );
assertThat( target.getS() ).isEqualTo( "3" );
assertThat( target.getSs() ).isEqualTo( "4" );
assertThat( target.getI() ).isEqualTo( "5" );
assertThat( target.getIi() ).isEqualTo( "6" );
assertThat( target.getL() ).isEqualTo( "7" );
assertThat( target.getLl() ).isEqualTo( "8" );
assertThat( target.getF() ).isEqualTo( "9.0" );
assertThat( target.getFf() ).isEqualTo( "10.0" );
assertThat( target.getD() ).isEqualTo( "11.0" );
assertThat( target.getDd() ).isEqualTo( "12.0" );
assertThat( target.getBool() ).isEqualTo( "true" );
assertThat( target.getBoolBool() ).isEqualTo( "true" );
assertThat( target.getC() ).isEqualTo( "G" );
assertThat( target.getCc() ).isEqualTo( "H" );
}
@Test
public void shouldApplyReverseStringConversions() {
Target target = new Target();
target.setB( "1" );
target.setBb( "2" );
target.setS( "3" );
target.setSs( "4" );
target.setI( "5" );
target.setIi( "6" );
target.setL( "7" );
target.setLl( "8" );
target.setF( "9.0" );
target.setFf( "10.0" );
target.setD( "11.0" );
target.setDd( "12.0" );
target.setBool( "true" );
target.setBoolBool( "true" );
target.setC( "G" );
target.setCc( "H" );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
assertThat( source ).isNotNull();
assertThat( source.getB() ).isEqualTo( (byte) 1 );
assertThat( source.getBb() ).isEqualTo( Byte.valueOf( (byte) 2 ) );
assertThat( source.getS() ).isEqualTo( (short) 3 );
assertThat( source.getSs() ).isEqualTo( Short.valueOf( (short) 4 ) );
assertThat( source.getI() ).isEqualTo( 5 );
assertThat( source.getIi() ).isEqualTo( Integer.valueOf( 6 ) );
assertThat( source.getL() ).isEqualTo( 7 );
assertThat( source.getLl() ).isEqualTo( Long.valueOf( 8 ) );
assertThat( source.getF() ).isEqualTo( 9f );
assertThat( source.getFf() ).isEqualTo( Float.valueOf( 10f ) );
assertThat( source.getD() ).isEqualTo( 11d );
assertThat( source.getDd() ).isEqualTo( Double.valueOf( 12d ) );
assertThat( source.getBool() ).isEqualTo( true );
assertThat( source.getBoolBool() ).isEqualTo( true );
assertThat( source.getC() ).isEqualTo( 'G' );
assertThat( source.getCc() ).isEqualTo( 'H' );
}
}

View File

@ -0,0 +1,168 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* 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 org.mapstruct.ap.test.conversion.string;
public class Target {
private String b;
private String bb;
private String s;
private String ss;
private String i;
private String ii;
private String l;
private String ll;
private String f;
private String ff;
private String d;
private String dd;
private String bool;
private String boolBool;
private String c;
private String cc;
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getBb() {
return bb;
}
public void setBb(String bb) {
this.bb = bb;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
public String getSs() {
return ss;
}
public void setSs(String ss) {
this.ss = ss;
}
public String getI() {
return i;
}
public void setI(String i) {
this.i = i;
}
public String getIi() {
return ii;
}
public void setIi(String ii) {
this.ii = ii;
}
public String getL() {
return l;
}
public void setL(String l) {
this.l = l;
}
public String getLl() {
return ll;
}
public void setLl(String ll) {
this.ll = ll;
}
public String getF() {
return f;
}
public void setF(String f) {
this.f = f;
}
public String getFf() {
return ff;
}
public void setFf(String ff) {
this.ff = ff;
}
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
public String getDd() {
return dd;
}
public void setDd(String dd) {
this.dd = dd;
}
public String getBool() {
return bool;
}
public void setBool(String bool) {
this.bool = bool;
}
public String getBoolBool() {
return boolBool;
}
public void setBoolBool(String boolBool) {
this.boolBool = boolBool;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
public String getCc() {
return cc;
}
public void setCc(String cc) {
this.cc = cc;
}
}