diff --git a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java index a311dfded..de640049a 100644 --- a/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java +++ b/processor/src/main/java/org/mapstruct/ap/MapperGenerationVisitor.java @@ -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 { } 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 methods, Method method) { diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/CharToStringConversion.java similarity index 89% rename from processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java rename to processor/src/main/java/org/mapstruct/ap/conversion/CharToStringConversion.java index 4bbc0607a..c0f8e08ee 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/IntStringConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/CharToStringConversion.java @@ -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 )"; } } diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/CharWrapperToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/CharWrapperToStringConversion.java new file mode 100644 index 000000000..95d35e2fb --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/CharWrapperToStringConversion.java @@ -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 )"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java index 857a3b93c..4b3527838 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java @@ -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 ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/PrimitiveToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/PrimitiveToStringConversion.java new file mode 100644 index 000000000..7edce71c7 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/PrimitiveToStringConversion.java @@ -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> primitiveToWrapperTypes; + + static { + Map, Class> tmp = new HashMap, 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 + " )"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/WrapperToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/WrapperToStringConversion.java new file mode 100644 index 000000000..f6ef9766f --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/WrapperToStringConversion.java @@ -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> wrapperToPrimitiveTypes; + + static { + Map, Class> tmp = new HashMap, 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 + " )"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/util/Strings.java b/processor/src/main/java/org/mapstruct/ap/util/Strings.java new file mode 100644 index 000000000..ad617def3 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/util/Strings.java @@ -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 ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Source.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Source.java new file mode 100644 index 000000000..da2008968 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Source.java @@ -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; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/string/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/SourceTargetMapper.java new file mode 100644 index 000000000..6c45e4a0a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/SourceTargetMapper.java @@ -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); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/string/StringConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/StringConversionTest.java new file mode 100644 index 000000000..0755f250e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/StringConversionTest.java @@ -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' ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Target.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Target.java new file mode 100644 index 000000000..3b452ef74 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/string/Target.java @@ -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; + } + +}