From 080689b345ae33d24fb059b529bfa3a2291319f2 Mon Sep 17 00:00:00 2001 From: Timo E aus E Date: Mon, 28 Apr 2014 19:01:00 +0200 Subject: [PATCH] #75 got rid of hard dependency to joda library and added conversions for java.util.Date and java.util.Calendar --- parent/pom.xml | 1 + .../AbstractJodaTypeToStringConversion.java | 105 +++++++++++++ .../mapstruct/ap/conversion/Conversions.java | 90 +++++++++-- .../JodaDateTimeToStringConversion.java | 35 +++++ .../JodaLocalDateTimeToStringConversion.java | 35 +++++ .../JodaLocalDateToStringConversion.java | 35 +++++ .../JodaLocalTimeToStringConversion.java | 35 +++++ .../ap/conversion/JodaTimeConstants.java | 38 +++++ .../JodaTimeToCalendarConversion.java | 51 ++++++ .../conversion/JodaTimeToDateConversion.java | 55 +++++++ .../JodaTypeToStringConversion.java | 147 ------------------ .../org/mapstruct/ap/util/ClassUtils.java | 42 +++++ .../jodatime/JodaConversionTest.java | 106 ++++++++++++- .../ap/test/conversion/jodatime/Source.java | 20 +++ .../jodatime/SourceTargetMapper.java | 17 ++ .../ap/test/conversion/jodatime/Target.java | 23 +++ 16 files changed, 674 insertions(+), 161 deletions(-) create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalTimeToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToCalendarConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToDateConversion.java delete mode 100644 processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java create mode 100644 processor/src/main/java/org/mapstruct/ap/util/ClassUtils.java diff --git a/parent/pom.xml b/parent/pom.xml index eb6533f69..8f6274d53 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -182,6 +182,7 @@ joda-time joda-time 2.3 + test diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java new file mode 100644 index 000000000..5a658506d --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java @@ -0,0 +1,105 @@ +/** + * 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.mapstruct.ap.model.TypeConversion; +import org.mapstruct.ap.model.common.ConversionContext; +import org.mapstruct.ap.model.common.Type; +import org.mapstruct.ap.util.Strings; + +import java.util.Collections; +import java.util.Locale; + +import static org.mapstruct.ap.util.Collections.asSet; + +/** + * + */ +public abstract class AbstractJodaTypeToStringConversion implements ConversionProvider { + + public TypeConversion to(String sourceReference, ConversionContext conversionContext) { + return new TypeConversion( + asSet( + conversionContext.getTypeFactory().getType( dateTimeFormatClass() ), + conversionContext.getTypeFactory().getType( Locale.class ) ), + Collections.emptyList(), + conversionString( sourceReference, conversionContext, "print" ) + ); + } + + public TypeConversion from(String targetReference, ConversionContext conversionContext) { + return new TypeConversion( + asSet( + conversionContext.getTypeFactory().getType( dateTimeFormatClass() ) ), + Collections.emptyList(), + conversionString( + targetReference, + conversionContext, + parseMethod() ) + ); + } + + 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) { + StringBuilder conversionString = new StringBuilder(); + conversionString.append( ".forPattern(" ); + + String dateFormat = conversionContext.getDateFormat(); + if ( Strings.isEmpty( dateFormat ) ) { + conversionString.append( defaultDateFormatPattern() ); + + } + else { + conversionString.append( " \"" ); + conversionString.append( dateFormat ); + conversionString.append( "\"" ); + + } + conversionString.append( ")" ); + return conversionString.toString(); + } + + public String defaultDateFormatPattern() { + return "DateTimeFormat.patternForStyle( \"" + formatStyle() + "\", Locale.getDefault() )"; + } + + protected abstract String formatStyle(); + + protected abstract String parseMethod(); + + private Class dateTimeFormatClass() { + try { + return Class.forName( "org.joda.time.format.DateTimeFormat" ); + } + catch ( ClassNotFoundException e ) { + throw new RuntimeException( "org.joda.time.format.DateTimeFormat not found on classpath" ); + } + } + +} 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 4fdd365cc..856947b4c 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java @@ -20,17 +20,15 @@ package org.mapstruct.ap.conversion; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Calendar; import java.util.Date; 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; +import org.mapstruct.ap.util.ClassUtils; import static org.mapstruct.ap.conversion.ReverseConversion.reverse; @@ -181,11 +179,7 @@ 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 ) ); + registerJoda(); //misc. register( Enum.class, String.class, new EnumStringConversion() ); @@ -193,6 +187,83 @@ public class Conversions { register( BigDecimal.class, BigInteger.class, new BigDecimalToBigIntegerConversion() ); } + private void registerJoda() { + if ( isJodaTimeAvailable() ) { + // joda to string + tryRegisterClassByName( + JodaTimeConstants.DATE_TIME_FQN, + String.class, + new JodaDateTimeToStringConversion() + ); + tryRegisterClassByName( + JodaTimeConstants.LOCAL_DATE_FQN, + String.class, + new JodaLocalDateToStringConversion() + ); + tryRegisterClassByName( + JodaTimeConstants.LOCAL_DATE_TIME_FQN, + String.class, + new JodaLocalDateTimeToStringConversion() + ); + tryRegisterClassByName( + JodaTimeConstants.LOCAL_TIME_FQN, + String.class, + new JodaLocalTimeToStringConversion() + ); + + // joda to date + tryRegisterClassByName( + JodaTimeConstants.DATE_TIME_FQN, + Date.class, + new JodaTimeToDateConversion() + ); + tryRegisterClassByName( + JodaTimeConstants.LOCAL_DATE_FQN, + Date.class, + new JodaTimeToDateConversion() + ); + tryRegisterClassByName( + JodaTimeConstants.LOCAL_DATE_TIME_FQN, + Date.class, + new JodaTimeToDateConversion() + ); + + tryRegisterClassByName( + JodaTimeConstants.DATE_TIME_FQN, + Calendar.class, + new JodaTimeToCalendarConversion() + ); + } + } + + private static boolean isJodaTimeAvailable() { + return ClassUtils.isTypeAvailable( JodaTimeConstants.DATE_TIME_FQN ); + } + + /** + * Invokes + *
    + *
  1. {@link Class#forName(String)}
  2. + *
  3. {@link org.mapstruct.ap.conversion.Conversions#register(Class, Class, ConversionProvider)}
  4. + *
+ * with the instance returned from 1. + * + * @param fullQualifiedClassName Name of type that should be reigstered + * @param target Target for {@link Conversions#register(Class, Class, ConversionProvider)} + * @param conversionProvider conversionProvider for + * {@link Conversions#register(Class, Class, ConversionProvider)} + */ + private void tryRegisterClassByName(String fullQualifiedClassName, Class target, + ConversionProvider conversionProvider) { + try { + Class classByName = Class.forName( fullQualifiedClassName ); + register( classByName, target, conversionProvider ); + } + catch ( ClassNotFoundException e ) { + throw new RuntimeException( e ); // rethrow exception? + } + } + private void registerNativeTypeConversion(Class sourceType, Class targetType) { if ( sourceType.isPrimitive() && targetType.isPrimitive() ) { register( sourceType, targetType, new PrimitiveToPrimitiveConversion( sourceType ) ); @@ -262,7 +333,6 @@ public class Conversions { private final Type sourceType; private final Type targetType; - private Key(Type sourceType, Type targetType) { this.sourceType = sourceType; this.targetType = targetType; diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java new file mode 100644 index 000000000..69b6a5ba2 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java @@ -0,0 +1,35 @@ +/** + * 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; + +/** + * + */ +public class JodaDateTimeToStringConversion extends AbstractJodaTypeToStringConversion { + + @Override + protected String formatStyle() { + return JodaTimeConstants.DATE_TIME_FORMAT; + } + + @Override + protected String parseMethod() { + return "parseDateTime"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java new file mode 100644 index 000000000..20f78b639 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java @@ -0,0 +1,35 @@ +/** + * 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; + +/** + * + */ +public class JodaLocalDateTimeToStringConversion extends AbstractJodaTypeToStringConversion { + + @Override + protected String formatStyle() { + return JodaTimeConstants.DATE_TIME_FORMAT; + } + + @Override + protected String parseMethod() { + return "parseLocalDateTime"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateToStringConversion.java new file mode 100644 index 000000000..7b644e146 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateToStringConversion.java @@ -0,0 +1,35 @@ +/** + * 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; + +/** + * + */ +public class JodaLocalDateToStringConversion extends AbstractJodaTypeToStringConversion { + + @Override + protected String formatStyle() { + return "L-"; + } + + @Override + protected String parseMethod() { + return "parseLocalDate"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalTimeToStringConversion.java new file mode 100644 index 000000000..81b116237 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalTimeToStringConversion.java @@ -0,0 +1,35 @@ +/** + * 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; + +/** + * + */ +public class JodaLocalTimeToStringConversion extends AbstractJodaTypeToStringConversion { + + @Override + protected String formatStyle() { + return "-L"; + } + + @Override + protected String parseMethod() { + return "parseLocalTime"; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java new file mode 100644 index 000000000..fbe6b8f59 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java @@ -0,0 +1,38 @@ +/** + * 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; + +/** + * Helper holding constants for working with joda time + */ +public final class JodaTimeConstants { + + private JodaTimeConstants() { + } + + public static final String DATE_TIME_FQN = "org.joda.time.DateTime"; + + public static final String LOCAL_DATE_TIME_FQN = "org.joda.time.LocalDateTime"; + + public static final String LOCAL_DATE_FQN = "org.joda.time.LocalDate"; + + public static final String LOCAL_TIME_FQN = "org.joda.time.LocalTime"; + + public static final String DATE_TIME_FORMAT = "LL"; +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToCalendarConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToCalendarConversion.java new file mode 100644 index 000000000..5f690c840 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToCalendarConversion.java @@ -0,0 +1,51 @@ +/** + * 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.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 JodaTimeToCalendarConversion implements ConversionProvider { + + @Override + public TypeConversion to(String sourceReference, ConversionContext conversionContext) { + return new TypeConversion( + asSet( conversionContext.getTypeFactory().getType( Locale.class ) ), + Collections.emptyList(), + sourceReference + ".toCalendar( Locale.getDefault() )" ); + } + + @Override + public TypeConversion from(String targetReference, ConversionContext conversionContext) { + return new TypeConversion( + Collections.emptySet(), + Collections.emptyList(), + "new " + conversionContext.getTargetType().getFullyQualifiedName() + "( " + targetReference + + " )" ); + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToDateConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToDateConversion.java new file mode 100644 index 000000000..685e95cdb --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeToDateConversion.java @@ -0,0 +1,55 @@ +/** + * 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.mapstruct.ap.model.TypeConversion; +import org.mapstruct.ap.model.common.ConversionContext; +import org.mapstruct.ap.model.common.Type; + +import java.util.Collections; + +/** + * Implementation of {@link org.mapstruct.ap.conversion.ConversionProvider} mapping Joda Types + *
    + *
  • org.joda.time.DateTime
  • + *
  • org.joda.time.LocalDateTime
  • + *
  • org.joda.time.LocalDate
  • + *
+ * to java.util.Date by invoking org.joda.time.base.AbstractInstant#toDate(). + * Backward conversion is done. + */ +public class JodaTimeToDateConversion implements ConversionProvider { + + @Override + public TypeConversion to(String sourceReference, ConversionContext conversionContext) { + return new TypeConversion( + Collections.emptySet(), + Collections.emptyList(), + sourceReference + ".toDate()" ); + } + + @Override + public TypeConversion from(String targetReference, ConversionContext conversionContext) { + return new TypeConversion( + Collections.emptySet(), + Collections.emptyList(), + "new " + conversionContext.getTargetType().getFullyQualifiedName() + "( " + targetReference + + " )" ); + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java deleted file mode 100644 index 907bfd2bd..000000000 --- a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTypeToStringConversion.java +++ /dev/null @@ -1,147 +0,0 @@ -/** - * 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/main/java/org/mapstruct/ap/util/ClassUtils.java b/processor/src/main/java/org/mapstruct/ap/util/ClassUtils.java new file mode 100644 index 000000000..f4f4f9b98 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/util/ClassUtils.java @@ -0,0 +1,42 @@ +/** + * 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.util; + +/** + * + */ +public final class ClassUtils { + + private ClassUtils() { } + /** + * Determines if the type with the given full qualified name is part of the classpath + * + * @param fullQualifiedClassName Name of the type to be checked for availability + * @return true if the type with the given full qualified name is part of the classpath. + */ + public static boolean isTypeAvailable(String fullQualifiedClassName) { + try { + Class.forName( fullQualifiedClassName ); + } + catch ( ClassNotFoundException e ) { + return false; + } + return true; + } +} 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 index 67db3032e..303e6c670 100644 --- 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 @@ -29,14 +29,17 @@ import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import java.util.Calendar; +import java.util.TimeZone; + import static org.fest.assertions.Assertions.assertThat; /** * */ @RunWith(AnnotationProcessorTestRunner.class) -@WithClasses( { Source.class, Target.class, SourceTargetMapper.class } ) -@IssueKey( "75" ) +@WithClasses({ Source.class, Target.class, SourceTargetMapper.class }) +@IssueKey("75") public class JodaConversionTest { @Test @@ -76,13 +79,24 @@ public class JodaConversionTest { } @Test - public void testSourceToTargetMapping() { + public void testSourceToTargetMappingForStrings() { 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 ) ); + + // with given format 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" ); + + // and now with default mappings + target = SourceTargetMapper.INSTANCE.sourceToTargetDefaultMapping( src ); assertThat( target ).isNotNull(); assertThat( target.getDateTime() ).isEqualTo( "01.01.2014 00:00 UTC" ); assertThat( target.getLocalDateTime() ).isEqualTo( "01.01.2014 00:00" ); @@ -98,9 +112,93 @@ public class JodaConversionTest { DateTime sourceDateTime = new DateTime( 2014, 1, 1, 0, 0, 0, DateTimeZone.UTC ); - Source src = SourceTargetMapper.INSTANCE.targetToSource( target ); + Source src = SourceTargetMapper.INSTANCE.targetToSourceDateTimeMapped( target ); assertThat( src ).isNotNull(); assertThat( src.getDateTime() ).isEqualTo( sourceDateTime ); } + @Test + public void testStringToLocalDateTime() { + String dateTimeAsString = "01.01.2014 00:00"; + Target target = new Target(); + target.setLocalDateTime( dateTimeAsString ); + LocalDateTime sourceDateTime = + new LocalDateTime( 2014, 1, 1, 0, 0, 0 ); + + Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalDateTimeMapped( target ); + assertThat( src ).isNotNull(); + assertThat( src.getLocalDateTime() ).isEqualTo( sourceDateTime ); + } + + @Test + public void testStringToLocalDate() { + String dateTimeAsString = "01.01.2014"; + Target target = new Target(); + target.setLocalDate( dateTimeAsString ); + LocalDate sourceDate = + new LocalDate( 2014, 1, 1 ); + + Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalDateMapped( target ); + assertThat( src ).isNotNull(); + assertThat( src.getLocalDate() ).isEqualTo( sourceDate ); + } + + @Test + public void testStringToLocalTime() { + String dateTimeAsString = "00:00"; + Target target = new Target(); + target.setLocalTime( dateTimeAsString ); + LocalTime sourceTime = + new LocalTime( 0, 0 ); + + Source src = SourceTargetMapper.INSTANCE.targetToSourceLocalTimeMapped( target ); + assertThat( src ).isNotNull(); + assertThat( src.getLocalTime() ).isEqualTo( sourceTime ); + } + + @Test + public void testTargetToSourceNullMapping() { + Target target = new Target(); + Source src = SourceTargetMapper.INSTANCE.targetToSource( target ); + + assertThat( src ).isNotNull(); + assertThat( src.getDateTime() ).isNull(); + assertThat( src.getLocalDate() ).isNull(); + assertThat( src.getLocalDateTime() ).isNull(); + assertThat( src.getLocalTime() ).isNull(); + } + + @Test + public void testTargetToSourceMappingForStrings() { + Target target = new Target(); + + target.setDateTime( "01.01.2014 00:00 UTC" ); + target.setLocalDateTime( "01.01.2014 00:00" ); + target.setLocalDate( "01.01.2014" ); + target.setLocalTime( "00:00" ); + + Source src = SourceTargetMapper.INSTANCE.targetToSource( target ); + + assertThat( src.getDateTime() ).isEqualTo( new DateTime( 2014, 1, 1, 0, 0, DateTimeZone.UTC ) ); + assertThat( src.getLocalDateTime() ).isEqualTo( new LocalDateTime( 2014, 1, 1, 0, 0 ) ); + assertThat( src.getLocalDate() ).isEqualTo( new LocalDate( 2014, 1, 1 ) ); + assertThat( src.getLocalTime() ).isEqualTo( new LocalTime( 0, 0 ) ); + } + + @Test + public void testCalendar() { + Calendar calendar = Calendar.getInstance( TimeZone.getTimeZone( "CET" ) ); + DateTime dateTimeWithCalendar = new DateTime( calendar ); + + Source src = new Source(); + src.setDateTimeForCalendarConversion( dateTimeWithCalendar ); + Target target = SourceTargetMapper.INSTANCE.sourceToTarget( src ); + assertThat( target ).isNotNull(); + assertThat( target.getDateTimeForCalendarConversion() ).isEqualTo( calendar ); + + Source mappedSource = SourceTargetMapper.INSTANCE.targetToSource( target ); + assertThat( mappedSource ).isNotNull(); + assertThat( mappedSource.getDateTimeForCalendarConversion() ).isEqualTo( dateTimeWithCalendar ); + + } } 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 index 35638027f..95554a5de 100644 --- 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 @@ -36,6 +36,10 @@ public class Source { private LocalTime localTime; + private DateTime dateTimeForDateConversion; + + private DateTime dateTimeForCalendarConversion; + public DateTime getDateTime() { return dateTime; } @@ -67,4 +71,20 @@ public class Source { public void setLocalTime(LocalTime localTime) { this.localTime = localTime; } + + public DateTime getDateTimeForDateConversion() { + return dateTimeForDateConversion; + } + + public void setDateTimeForDateConversion(DateTime dateTimeForDateConversion) { + this.dateTimeForDateConversion = dateTimeForDateConversion; + } + + public DateTime getDateTimeForCalendarConversion() { + return dateTimeForCalendarConversion; + } + + public void setDateTimeForCalendarConversion(DateTime dateTimeForCalendarConversion) { + this.dateTimeForCalendarConversion = dateTimeForCalendarConversion; + } } 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 index cd41934b2..c4c7f4aa7 100644 --- 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 @@ -38,12 +38,15 @@ public interface SourceTargetMapper { 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); + Target sourceToTargetDefaultMapping(Source source); + @Mapping( source = "dateTime", dateFormat = DATE_TIME_FORMAT ) Target sourceToTargetDateTimeMapped(Source source); @@ -62,4 +65,18 @@ public interface SourceTargetMapper { @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ), @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) }) Source targetToSource(Target target); + + @Mapping( source = "dateTime", dateFormat = DATE_TIME_FORMAT ) + Source targetToSourceDateTimeMapped(Target target); + + @Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ) + Source targetToSourceLocalDateTimeMapped(Target target); + + @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ) + Source targetToSourceLocalDateMapped(Target target); + + @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) + Source targetToSourceLocalTimeMapped(Target target); + + Source targetToSourceDefaultMapping(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 index 6d227009b..835f2a36e 100644 --- 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 @@ -18,6 +18,9 @@ */ package org.mapstruct.ap.test.conversion.jodatime; +import java.util.Calendar; +import java.util.Date; + /** * */ @@ -31,6 +34,10 @@ public class Target { private String localTime; + private Date dateTimeForDateConversion; + + private Calendar dateTimeForCalendarConversion; + public String getDateTime() { return dateTime; } @@ -62,4 +69,20 @@ public class Target { public void setLocalTime(String localTime) { this.localTime = localTime; } + + public Date getDateTimeForDateConversion() { + return dateTimeForDateConversion; + } + + public void setDateTimeForDateConversion(Date dateTimeForDateConversion) { + this.dateTimeForDateConversion = dateTimeForDateConversion; + } + + public Calendar getDateTimeForCalendarConversion() { + return dateTimeForCalendarConversion; + } + + public void setDateTimeForCalendarConversion(Calendar dateTimeForCalendarConversion) { + this.dateTimeForCalendarConversion = dateTimeForCalendarConversion; + } }