diff --git a/parent/pom.xml b/parent/pom.xml
index f00b641db..eb6533f69 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -177,6 +177,13 @@
${org.springframework.version}
+
+
+ joda-time
+ joda-time
+ 2.3
+
+
${project.groupId}
diff --git a/processor/pom.xml b/processor/pom.xml
index df04136bd..87e8ea0df 100644
--- a/processor/pom.xml
+++ b/processor/pom.xml
@@ -57,7 +57,11 @@
mapstruct
provided
-
+
+
+ joda-time
+ joda-time
+
junit
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 15e977fa8..4fdd365cc 100644
--- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java
@@ -25,6 +25,10 @@ import java.util.HashMap;
import java.util.Map;
import javax.lang.model.util.Elements;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
import org.mapstruct.ap.model.common.Type;
import org.mapstruct.ap.model.common.TypeFactory;
@@ -177,6 +181,12 @@ public class Conversions {
register( BigInteger.class, String.class, new BigIntegerToStringConversion() );
register( BigDecimal.class, String.class, new BigDecimalToStringConversion() );
+ // joda
+ register( DateTime.class, String.class, new JodaTypeToStringConversion( DateTime.class ) );
+ register( LocalDate.class, String.class, new JodaTypeToStringConversion( LocalDate.class ) );
+ register( LocalTime.class, String.class, new JodaTypeToStringConversion( LocalTime.class ) );
+ register( LocalDateTime.class, String.class, new JodaTypeToStringConversion( LocalDateTime.class ) );
+
//misc.
register( Enum.class, String.class, new EnumStringConversion() );
register( Date.class, String.class, new DateToStringConversion() );
diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java
new file mode 100644
index 000000000..907bfd2bd
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2012-2014 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.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+import org.joda.time.format.DateTimeFormat;
+import org.mapstruct.ap.model.TypeConversion;
+import org.mapstruct.ap.model.common.ConversionContext;
+import org.mapstruct.ap.model.common.Type;
+
+import java.util.Collections;
+import java.util.Locale;
+
+import static org.mapstruct.ap.util.Collections.asSet;
+
+/**
+ *
+ */
+public class JodaTypeToStringConversion implements ConversionProvider {
+
+ private final Class sourceType;
+
+ public JodaTypeToStringConversion(Class sourceType) {
+
+ this.sourceType = sourceType;
+ }
+
+ public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
+ return new TypeConversion(
+ asSet(
+ conversionContext.getTypeFactory().getType( DateTimeFormat.class ),
+ conversionContext.getTypeFactory().getType( DateTime.class ) ),
+ Collections.emptyList(),
+ conversionString( sourceReference, conversionContext, "print" )
+ );
+ }
+
+ public TypeConversion from(String targetReference, ConversionContext conversionContext) {
+ return new TypeConversion(
+ asSet(
+ conversionContext.getTypeFactory().getType( DateTimeFormat.class ),
+ conversionContext.getTypeFactory().getType( DateTime.class ) ),
+ Collections.emptyList(),
+ conversionString(
+ targetReference,
+ conversionContext,
+ parseMethodForTargetType( conversionContext ) )
+ );
+ }
+
+ private String parseMethodForTargetType(ConversionContext conversionContext) {
+ if ( DateTime.class.getName().equals( conversionContext.getTargetType().getFullyQualifiedName() ) ) {
+ return "parseDateTime";
+ }
+ else if ( LocalDateTime.class.getName().equals( conversionContext.getTargetType().getFullyQualifiedName() ) ) {
+ return "parseLocalDateTime";
+ }
+ else if ( LocalDate.class.getName().equals( conversionContext.getTargetType().getFullyQualifiedName() ) ) {
+ return "parseLocalDate";
+ }
+ else if ( LocalTime.class.getName().equals( conversionContext.getTargetType().getFullyQualifiedName() ) ) {
+ return "parseLocalTime";
+ }
+ else {
+ throw new RuntimeException(
+ String.format(
+ "Joda type %s not supported (yet)",
+ conversionContext.getTargetType() )
+ );
+ }
+ }
+
+ private String conversionString(String reference, ConversionContext conversionContext, String method) {
+ StringBuilder conversionString = new StringBuilder( "DateTimeFormat" );
+ conversionString.append( dateFormatPattern( conversionContext ) );
+ conversionString.append( "." );
+ conversionString.append( method );
+ conversionString.append( "( " );
+ conversionString.append( reference );
+ conversionString.append( " )" );
+ return conversionString.toString();
+ }
+
+ private String dateFormatPattern(ConversionContext conversionContext) {
+ String dateFormat = conversionContext.getDateFormat();
+ if ( isBlank( dateFormat ) ) {
+ dateFormat = defaultDateFormatPattern( sourceType );
+ }
+ StringBuilder conversionString = new StringBuilder();
+ conversionString.append( ".forPattern( \"" );
+ conversionString.append( dateFormat );
+ conversionString.append( "\" )" );
+ return conversionString.toString();
+ }
+
+ public static String defaultDateFormatPattern(Class sourceType) {
+ return DateTimeFormat.patternForStyle( formatStyle( sourceType ), Locale.getDefault() );
+ }
+
+ private static String formatStyle(Class sourceType) {
+ if ( DateTime.class == sourceType ) {
+ return "LL";
+ }
+ else if ( LocalDateTime.class == sourceType ) {
+ return "LL";
+ }
+ else if ( LocalDate.class == sourceType ) {
+ return "L-";
+ }
+ else if ( LocalTime.class == sourceType ) {
+ return "-L";
+ }
+ else {
+ throw new RuntimeException(
+ String.format(
+ "Joda type %s not supported (yet)",
+ sourceType )
+ );
+ }
+ }
+
+ // ugly. would be nice to have something like commons-lang or
+ // guava on classpath. Or something homebrewn for
+ // these kind of checks, assertions, etc.
+ private boolean isBlank(String str) {
+ return str == null || ( str != null && str.trim().equals( "" ) );
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java
new file mode 100644
index 000000000..67db3032e
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2012-2014 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.jodatime;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mapstruct.ap.testutil.IssueKey;
+import org.mapstruct.ap.testutil.WithClasses;
+import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ *
+ */
+@RunWith(AnnotationProcessorTestRunner.class)
+@WithClasses( { Source.class, Target.class, SourceTargetMapper.class } )
+@IssueKey( "75" )
+public class JodaConversionTest {
+
+ @Test
+ public void testDateTimeToString() {
+ Source src = new Source();
+ src.setDateTime( new DateTime( 2014, 1, 1, 0, 0, 0, DateTimeZone.UTC ) );
+ Target target = SourceTargetMapper.INSTANCE.sourceToTargetDateTimeMapped( src );
+ assertThat( target ).isNotNull();
+ assertThat( target.getDateTime() ).isEqualTo( "01.01.2014 00:00 UTC" );
+ }
+
+ @Test
+ public void testLocalDateTimeToString() {
+ Source src = new Source();
+ src.setLocalDateTime( new LocalDateTime( 2014, 1, 1, 0, 0 ) );
+ Target target = SourceTargetMapper.INSTANCE.sourceToTargetLocalDateTimeMapped( src );
+ assertThat( target ).isNotNull();
+ assertThat( target.getLocalDateTime() ).isEqualTo( "01.01.2014 00:00" );
+ }
+
+ @Test
+ public void testLocalDateToString() {
+ Source src = new Source();
+ src.setLocalDate( new LocalDate( 2014, 1, 1 ) );
+ Target target = SourceTargetMapper.INSTANCE.sourceToTargetLocalDateMapped( src );
+ assertThat( target ).isNotNull();
+ assertThat( target.getLocalDate() ).isEqualTo( "01.01.2014" );
+ }
+
+ @Test
+ public void testLocalTimeToString() {
+ Source src = new Source();
+ src.setLocalTime( new LocalTime( 0, 0 ) );
+ Target target = SourceTargetMapper.INSTANCE.sourceToTargetLocalTimeMapped( src );
+ assertThat( target ).isNotNull();
+ assertThat( target.getLocalTime() ).isEqualTo( "00:00" );
+ }
+
+ @Test
+ public void testSourceToTargetMapping() {
+ Source src = new Source();
+ src.setLocalTime( new LocalTime( 0, 0 ) );
+ src.setLocalDate( new LocalDate( 2014, 1, 1 ) );
+ src.setLocalDateTime( new LocalDateTime( 2014, 1, 1, 0, 0 ) );
+ src.setDateTime( new DateTime( 2014, 1, 1, 0, 0, 0, DateTimeZone.UTC ) );
+ Target target = SourceTargetMapper.INSTANCE.sourceToTarget( src );
+ assertThat( target ).isNotNull();
+ assertThat( target.getDateTime() ).isEqualTo( "01.01.2014 00:00 UTC" );
+ assertThat( target.getLocalDateTime() ).isEqualTo( "01.01.2014 00:00" );
+ assertThat( target.getLocalDate() ).isEqualTo( "01.01.2014" );
+ assertThat( target.getLocalTime() ).isEqualTo( "00:00" );
+ }
+
+ @Test
+ public void testStringToDateTime() {
+ String dateTimeAsString = "01.01.2014 00:00 UTC";
+ Target target = new Target();
+ target.setDateTime( dateTimeAsString );
+ DateTime sourceDateTime =
+ new DateTime( 2014, 1, 1, 0, 0, 0, DateTimeZone.UTC );
+
+ Source src = SourceTargetMapper.INSTANCE.targetToSource( target );
+ assertThat( src ).isNotNull();
+ assertThat( src.getDateTime() ).isEqualTo( sourceDateTime );
+ }
+
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Source.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Source.java
new file mode 100644
index 000000000..35638027f
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Source.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2012-2014 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.jodatime;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+import org.joda.time.LocalTime;
+
+/**
+ *
+ */
+public class Source {
+
+ private DateTime dateTime;
+
+ private LocalDateTime localDateTime;
+
+ private LocalDate localDate;
+
+ private LocalTime localTime;
+
+ public DateTime getDateTime() {
+ return dateTime;
+ }
+
+ public void setDateTime(DateTime dateTime) {
+ this.dateTime = dateTime;
+ }
+
+ public LocalDateTime getLocalDateTime() {
+ return localDateTime;
+ }
+
+ public void setLocalDateTime(LocalDateTime localDateTime) {
+ this.localDateTime = localDateTime;
+ }
+
+ public LocalDate getLocalDate() {
+ return localDate;
+ }
+
+ public void setLocalDate(LocalDate localDate) {
+ this.localDate = localDate;
+ }
+
+ public LocalTime getLocalTime() {
+ return localTime;
+ }
+
+ public void setLocalTime(LocalTime localTime) {
+ this.localTime = localTime;
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java
new file mode 100644
index 000000000..cd41934b2
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2012-2014 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.jodatime;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
+import org.mapstruct.factory.Mappers;
+
+/**
+ *
+ */
+@Mapper
+public interface SourceTargetMapper {
+
+ String DATE_TIME_FORMAT = "dd.MM.yyyy HH:mm z";
+
+ String LOCAL_DATE_TIME_FORMAT = "dd.MM.yyyy HH:mm";
+
+ String LOCAL_DATE_FORMAT = "dd.MM.yyyy";
+
+ String LOCAL_TIME_FORMAT = "HH:mm";
+
+ SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
+ @Mappings({ @Mapping( source = "dateTime", dateFormat = DATE_TIME_FORMAT ),
+ @Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ),
+ @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ),
+ @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) })
+ Target sourceToTarget(Source source);
+
+ @Mapping( source = "dateTime", dateFormat = DATE_TIME_FORMAT )
+ Target sourceToTargetDateTimeMapped(Source source);
+
+ @Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT )
+ Target sourceToTargetLocalDateTimeMapped(Source source);
+
+ @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT )
+ Target sourceToTargetLocalDateMapped(Source source);
+
+ @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT )
+ Target sourceToTargetLocalTimeMapped(Source source);
+
+
+ @Mappings({ @Mapping( source = "dateTime", dateFormat = DATE_TIME_FORMAT ),
+ @Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ),
+ @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ),
+ @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) })
+ Source targetToSource(Target target);
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Target.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Target.java
new file mode 100644
index 000000000..6d227009b
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/Target.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2012-2014 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.jodatime;
+
+/**
+ *
+ */
+public class Target {
+
+ private String dateTime;
+
+ private String localDateTime;
+
+ private String localDate;
+
+ private String localTime;
+
+ public String getDateTime() {
+ return dateTime;
+ }
+
+ public void setDateTime(String dateTime) {
+ this.dateTime = dateTime;
+ }
+
+ public String getLocalDateTime() {
+ return localDateTime;
+ }
+
+ public void setLocalDateTime(String localDateTime) {
+ this.localDateTime = localDateTime;
+ }
+
+ public String getLocalDate() {
+ return localDate;
+ }
+
+ public void setLocalDate(String localDate) {
+ this.localDate = localDate;
+ }
+
+ public String getLocalTime() {
+ return localTime;
+ }
+
+ public void setLocalTime(String localTime) {
+ this.localTime = localTime;
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
index f3c1bb26d..c70fcd0a1 100644
--- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
+++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java
@@ -87,7 +87,12 @@ class CompilingStatement extends Statement {
}
};
- private static final List LIBRARIES = Arrays.asList( "mapstruct.jar", "guava.jar", "javax.inject.jar" );
+ private static final List LIBRARIES = Arrays.asList(
+ "mapstruct.jar",
+ "guava.jar",
+ "javax.inject.jar",
+ "joda-time.jar"
+ );
private final Statement next;
private final FrameworkMethod method;