diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java
old mode 100644
new mode 100755
index bd966bbf7..cff6ef505
--- a/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/AbstractJodaTypeToStringConversion.java
@@ -23,6 +23,7 @@ import java.util.Set;
import org.mapstruct.ap.model.common.ConversionContext;
import org.mapstruct.ap.model.common.Type;
+import org.mapstruct.ap.util.JodaTimeConstants;
import org.mapstruct.ap.util.Strings;
import static org.mapstruct.ap.util.Collections.asSet;
diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java
old mode 100644
new mode 100755
index 0e20d0f2c..b470d69cd
--- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.mapstruct.ap.model.common.Type;
import org.mapstruct.ap.model.common.TypeFactory;
import org.mapstruct.ap.util.JavaTimeConstants;
+import org.mapstruct.ap.util.JodaTimeConstants;
import org.mapstruct.ap.util.NativeTypes;
import static org.mapstruct.ap.conversion.ReverseConversion.reverse;
diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java
old mode 100644
new mode 100755
index e3dc17e58..8aedaa269
--- a/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaDateTimeToStringConversion.java
@@ -18,6 +18,8 @@
*/
package org.mapstruct.ap.conversion;
+import org.mapstruct.ap.util.JodaTimeConstants;
+
/**
* Conversion between {@code DateTime} and {@code String}.
*
diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java
old mode 100644
new mode 100755
index 5f7591fbc..beb890dd3
--- a/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java
+++ b/processor/src/main/java/org/mapstruct/ap/conversion/JodaLocalDateTimeToStringConversion.java
@@ -18,6 +18,8 @@
*/
package org.mapstruct.ap.conversion;
+import org.mapstruct.ap.util.JodaTimeConstants;
+
/**
* Conversion between {@code LocalDateTime} and {@code String}.
*
diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidationResult.java b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidationResult.java
new file mode 100755
index 000000000..c7f65f930
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidationResult.java
@@ -0,0 +1,49 @@
+/**
+ * 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.model.common;
+
+/**
+ * Reflects the result of a date format validation
+ */
+final class DateFormatValidationResult {
+
+ private final boolean isValid;
+ private final String validationInformation;
+
+ /**
+ * Create a new instance.
+ *
+ * @param isValid determines of the validation was successful.
+ * @param validationInformation a string representing the validation result
+ */
+ DateFormatValidationResult(boolean isValid, String validationInformation) {
+
+ this.isValid = isValid;
+ this.validationInformation = validationInformation;
+ }
+
+ public boolean isValid() {
+ return isValid;
+ }
+
+ public String validationInformation() {
+ return validationInformation;
+ }
+
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidator.java b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidator.java
new file mode 100755
index 000000000..835348286
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidator.java
@@ -0,0 +1,36 @@
+/**
+ * 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.model.common;
+
+/**
+ * An abstraction for validating {@link ConversionContext#getDateFormat()}. There are implementers for different date
+ * types such as Joda Time, Java8 Time and java.util.Date.
+ */
+interface DateFormatValidator {
+
+ /**
+ * Validate the given dateFormat.
+ *
+ * @param dateFormat string supposed to be used for date formatting and parsing.
+ *
+ * @return {@link DateFormatValidationResult} representing the validation result.
+ */
+ DateFormatValidationResult validate(String dateFormat);
+
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidatorFactory.java b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidatorFactory.java
new file mode 100755
index 000000000..62916610e
--- /dev/null
+++ b/processor/src/main/java/org/mapstruct/ap/model/common/DateFormatValidatorFactory.java
@@ -0,0 +1,192 @@
+/**
+ * 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.model.common;
+
+import org.mapstruct.ap.util.JavaTimeConstants;
+import org.mapstruct.ap.util.JodaTimeConstants;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+
+/**
+ * Factory for {@link DateFormatValidator}.
Based on the types of source / target type a specific {@link
+ * DateFormatValidator} will be instantiated.
- Joda Time
- Java 8 Time and
+ * - java.util.Date
are supported.
+ */
+final class DateFormatValidatorFactory {
+
+ private static final String JAVA_UTIL_DATE = "java.util.Date";
+
+ private static final String JAVA_TIME_FORMAT_DATE_TIME_FORMATTER = "java.time.format.DateTimeFormatter";
+
+ private static final String OF_PATTERN = "ofPattern";
+
+ private static final String ORG_JODA_TIME_FORMAT_DATE_TIME_FORMAT = "org.joda.time.format.DateTimeFormat";
+
+ private static final String FOR_PATTERN = "forPattern";
+ private static final String JAVAX_XML_DATATYPE_XMLGREGORIAN_CALENDAR = "javax.xml.datatype.XMLGregorianCalendar";
+
+ private DateFormatValidatorFactory() {
+ }
+
+ /**
+ * Create a new {@link DateFormatValidator} based on source/target type of a type conversion. Theirs typenames will
+ * be compared against the supported types to determine a validator.
+ *
+ * @param sourceType The source type
+ * @param targetType The target type
+ * @return a new {@link DateFormatValidator}
+ */
+ public static DateFormatValidator forTypes(final Type sourceType, final Type targetType) {
+ DateFormatValidator dateFormatValidator;
+
+ if ( isJavaUtilDateSupposed( sourceType, targetType ) ) {
+ dateFormatValidator = new SimpleDateFormatValidator();
+ }
+ else if ( isXmlGregorianCalendarSupposedToBeMapped( sourceType, targetType ) ) {
+ dateFormatValidator = new SimpleDateFormatValidator();
+ }
+ else if ( isJava8DateTimeSupposed( sourceType, targetType ) ) {
+ dateFormatValidator = new JavaDateTimeDateFormatValidator();
+ }
+ else if ( isJodaDateTimeSupposed( sourceType, targetType ) ) {
+ dateFormatValidator = new JodaTimeDateFormatValidator();
+ }
+ else {
+ dateFormatValidator = new DateFormatValidator() {
+ @Override
+ public DateFormatValidationResult validate(String dateFormat) {
+ return new DateFormatValidationResult(
+ true, String.format(
+ "No dateFormat cheeck is supported for types %s, %s", sourceType, targetType ) );
+ }
+ };
+ }
+ return dateFormatValidator;
+
+ }
+
+ private static boolean isXmlGregorianCalendarSupposedToBeMapped(Type sourceType, Type targetType) {
+ return typesEqualsOneOf(
+ sourceType, targetType, JAVAX_XML_DATATYPE_XMLGREGORIAN_CALENDAR );
+ }
+
+ private static boolean isJodaDateTimeSupposed(Type sourceType, Type targetType) {
+ return typesEqualsOneOf(
+ sourceType,
+ targetType,
+ JodaTimeConstants.LOCAL_DATE_FQN,
+ JodaTimeConstants.LOCAL_TIME_FQN,
+ JodaTimeConstants.LOCAL_DATE_TIME_FQN,
+ JodaTimeConstants.DATE_TIME_FQN );
+ }
+
+ private static boolean isJava8DateTimeSupposed(Type sourceType, Type targetType) {
+ return typesEqualsOneOf(
+ sourceType,
+ targetType,
+ JavaTimeConstants.LOCAL_DATE_FQN,
+ JavaTimeConstants.LOCAL_TIME_FQN,
+ JavaTimeConstants.LOCAL_DATE_TIME_FQN,
+ JavaTimeConstants.ZONED_DATE_TIME_FQN );
+ }
+
+ private static boolean isJavaUtilDateSupposed(Type sourceType, Type targetType) {
+ return JAVA_UTIL_DATE.equals( sourceType.getFullyQualifiedName() ) || JAVA_UTIL_DATE.equals(
+ targetType.getFullyQualifiedName() );
+ }
+
+ private static boolean typesEqualsOneOf(Type sourceType, Type targetType, String... typeNames) {
+ for ( String typeName : typeNames ) {
+ if ( typeName.equals( sourceType.getFullyQualifiedName() )
+ || typeName.equals( targetType.getFullyQualifiedName() ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static class JavaDateTimeDateFormatValidator implements DateFormatValidator {
+ @Override
+ public DateFormatValidationResult validate(String dateFormat) {
+ try {
+ Class> aClass = Class.forName( JAVA_TIME_FORMAT_DATE_TIME_FORMATTER );
+ Method ofPatternMethod = aClass.getMethod( OF_PATTERN, String.class );
+ ofPatternMethod.invoke( aClass, dateFormat );
+ return validDateFormat( dateFormat );
+ }
+ catch ( InvocationTargetException e ) {
+ return invalidDateFormat( dateFormat, e.getCause() );
+ }
+ catch ( Exception e ) {
+ return invalidDateFormat( dateFormat, e );
+ }
+ }
+ }
+
+ private static class JodaTimeDateFormatValidator implements DateFormatValidator {
+
+ @Override
+ public DateFormatValidationResult validate(String dateFormat) {
+ try {
+ Class> aClass = Class.forName( ORG_JODA_TIME_FORMAT_DATE_TIME_FORMAT );
+ Method forPatternMethod = aClass.getMethod( FOR_PATTERN, String.class );
+ forPatternMethod.invoke( aClass, dateFormat );
+ return validDateFormat( dateFormat );
+ }
+ catch ( InvocationTargetException e ) {
+ return invalidDateFormat( dateFormat, e.getCause() );
+ }
+ catch ( Exception e ) {
+ return invalidDateFormat( dateFormat, e );
+ }
+ }
+ }
+
+ private static class SimpleDateFormatValidator implements DateFormatValidator {
+
+ @Override
+ public DateFormatValidationResult validate(String dateFormat) {
+ try {
+ Class> aClass = Class.forName( SimpleDateFormat.class.getCanonicalName() );
+ aClass.getConstructor( String.class ).newInstance( dateFormat );
+ return validDateFormat( dateFormat );
+ }
+ catch ( InvocationTargetException e ) {
+ return invalidDateFormat( dateFormat, e.getCause() );
+ }
+ catch ( Exception e ) {
+ return invalidDateFormat( dateFormat, e );
+ }
+ }
+ }
+
+ private static DateFormatValidationResult validDateFormat(String dateFormat) {
+ return new DateFormatValidationResult(
+ true, String.format(
+ "given date format \"%s\" is valid.", dateFormat ) );
+ }
+
+ private static DateFormatValidationResult invalidDateFormat(String dateFormat, Throwable e) {
+ return new DateFormatValidationResult(
+ false, String.format(
+ "given date format \"%s\" is invalid. Message: \"%s\"", dateFormat, e.getMessage() ) );
+ }
+}
diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/DefaultConversionContext.java b/processor/src/main/java/org/mapstruct/ap/model/common/DefaultConversionContext.java
old mode 100644
new mode 100755
index c47a38bf4..da036746e
--- a/processor/src/main/java/org/mapstruct/ap/model/common/DefaultConversionContext.java
+++ b/processor/src/main/java/org/mapstruct/ap/model/common/DefaultConversionContext.java
@@ -18,6 +18,11 @@
*/
package org.mapstruct.ap.model.common;
+import org.mapstruct.ap.util.Strings;
+
+import javax.annotation.processing.Messager;
+import javax.tools.Diagnostic;
+
/**
* Default implementation of the {@link ConversionContext} passed to conversion providers.
*
@@ -25,14 +30,34 @@ package org.mapstruct.ap.model.common;
*/
public class DefaultConversionContext implements ConversionContext {
+ private final Messager messager;
+ private final Type sourceType;
private final Type targetType;
- private final String format;
+ private final String dateFormat;
private final TypeFactory typeFactory;
- public DefaultConversionContext(TypeFactory typeFactory, Type targetType, String format) {
+ public DefaultConversionContext(TypeFactory typeFactory, Messager messager, Type sourceType, Type targetType,
+ String dateFormat) {
this.typeFactory = typeFactory;
+ this.messager = messager;
+ this.sourceType = sourceType;
this.targetType = targetType;
- this.format = format;
+ this.dateFormat = dateFormat;
+ validateDateFormat();
+ }
+
+ /**
+ * Validate the dateFormat if it is not null
+ */
+ private void validateDateFormat() {
+ if ( !Strings.isEmpty( dateFormat ) ) {
+ DateFormatValidator dateFormatValidator = DateFormatValidatorFactory.forTypes( sourceType, targetType );
+ DateFormatValidationResult validationResult = dateFormatValidator.validate( dateFormat );
+
+ if ( !validationResult.isValid() ) {
+ messager.printMessage( Diagnostic.Kind.ERROR, validationResult.validationInformation() );
+ }
+ }
}
@Override
@@ -42,11 +67,15 @@ public class DefaultConversionContext implements ConversionContext {
@Override
public String getDateFormat() {
- return format;
+ return dateFormat;
}
@Override
public TypeFactory getTypeFactory() {
return typeFactory;
}
+
+ protected Messager getMessager() {
+ return messager;
+ }
}
diff --git a/processor/src/main/java/org/mapstruct/ap/processor/creation/MappingResolverImpl.java b/processor/src/main/java/org/mapstruct/ap/processor/creation/MappingResolverImpl.java
old mode 100644
new mode 100755
index 706f39bc3..b1a20eaf8
--- a/processor/src/main/java/org/mapstruct/ap/processor/creation/MappingResolverImpl.java
+++ b/processor/src/main/java/org/mapstruct/ap/processor/creation/MappingResolverImpl.java
@@ -246,7 +246,7 @@ public class MappingResolverImpl implements MappingResolver {
}
ConversionContext ctx =
- new DefaultConversionContext( typeFactory, targetType, dateFormat );
+ new DefaultConversionContext( typeFactory, messager, sourceType, targetType, dateFormat );
return conversionProvider.to( ctx );
}
@@ -276,7 +276,9 @@ public class MappingResolverImpl implements MappingResolver {
if ( matchingBuiltInMethod != null ) {
virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) );
- ConversionContext ctx = new DefaultConversionContext( typeFactory, targetType, dateFormat );
+ ConversionContext ctx = new DefaultConversionContext( typeFactory, messager,
+ sourceType,
+ targetType, dateFormat );
Assignment methodReference = AssignmentFactory.createMethodReference( matchingBuiltInMethod, ctx );
methodReference.setAssignment( AssignmentFactory.createDirect( sourceReference ) );
return methodReference;
diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java b/processor/src/main/java/org/mapstruct/ap/util/JodaTimeConstants.java
old mode 100644
new mode 100755
similarity index 97%
rename from processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java
rename to processor/src/main/java/org/mapstruct/ap/util/JodaTimeConstants.java
index f12eca96e..dbb3b254d
--- a/processor/src/main/java/org/mapstruct/ap/conversion/JodaTimeConstants.java
+++ b/processor/src/main/java/org/mapstruct/ap/util/JodaTimeConstants.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.mapstruct.ap.conversion;
+package org.mapstruct.ap.util;
/**
* Helper holding constants for working with Joda-Time.
diff --git a/processor/src/test/java/org/mapstruct/ap/model/common/DateFormatValidatorFactoryTest.java b/processor/src/test/java/org/mapstruct/ap/model/common/DateFormatValidatorFactoryTest.java
new file mode 100755
index 000000000..540904ad6
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/model/common/DateFormatValidatorFactoryTest.java
@@ -0,0 +1,184 @@
+/**
+ * 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.model.common;
+
+import org.junit.Test;
+import org.mapstruct.ap.testutil.IssueKey;
+import org.mapstruct.ap.util.JavaTimeConstants;
+import org.mapstruct.ap.util.JodaTimeConstants;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * Tests for {@link org.mapstruct.ap.model.common.DateFormatValidatorFactory}.
+ *
+ * @author Timo Eckhardt
+ */
+@IssueKey( "224" )
+public class DateFormatValidatorFactoryTest {
+
+ private static final String JAVA_LANG_STRING = "java.lang.String";
+
+ private TypeMirror voidTypeMirror = new TypeMirror() {
+
+ @Override
+ public List extends AnnotationMirror> getAnnotationMirrors() {
+ return null;
+ }
+
+ @Override
+ public A getAnnotation(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ public A[] getAnnotationsByType(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ public TypeKind getKind() {
+ return TypeKind.VOID;
+ }
+
+ @Override
+ public R accept(TypeVisitor v, P p) {
+ return null;
+ }
+ };
+
+ @Test
+ public void testUnsupportedTypes() {
+ Type sourceType = typeWithFQN( JAVA_LANG_STRING );
+ Type targetType = typeWithFQN( JAVA_LANG_STRING );
+ DateFormatValidator dateFormatValidator = DateFormatValidatorFactory.forTypes( sourceType, targetType );
+ assertThat( dateFormatValidator.validate( "XXXX" ).isValid() ).isTrue();
+ }
+
+ @Test
+ public void testJavaUtilDateValidator() {
+
+ Type sourceType = typeWithFQN( "java.util.Date" );
+ Type targetType = typeWithFQN( JAVA_LANG_STRING );
+
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+ }
+
+ @Test
+ public void testJodaTimeValidator() {
+
+ Type targetType = typeWithFQN( JAVA_LANG_STRING );
+
+ Type sourceType = typeWithFQN( JodaTimeConstants.DATE_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JodaTimeConstants.LOCAL_DATE_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JodaTimeConstants.LOCAL_DATE_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JodaTimeConstants.LOCAL_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+ }
+
+ @Test
+ public void testJavaTimeValidator() {
+
+ Type targetType = typeWithFQN( JAVA_LANG_STRING );
+
+ Type sourceType = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JavaTimeConstants.LOCAL_DATE_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JavaTimeConstants.LOCAL_DATE_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+
+ sourceType = typeWithFQN( JavaTimeConstants.LOCAL_TIME_FQN );
+ assertInvalidDateFormat( sourceType, targetType );
+ assertInvalidDateFormat( targetType, sourceType );
+ assertValidDateFormat( sourceType, targetType );
+ assertValidDateFormat( targetType, sourceType );
+ }
+
+ private void assertInvalidDateFormat(Type sourceType, Type targetType) {
+ DateFormatValidator dateFormatValidator = DateFormatValidatorFactory.forTypes( sourceType, targetType );
+ DateFormatValidationResult result = dateFormatValidator.validate( "qwertz" );
+ assertThat( result.isValid() ).isFalse();
+ }
+
+ private void assertValidDateFormat(Type sourceType, Type targetType) {
+ DateFormatValidator dateFormatValidator = DateFormatValidatorFactory.forTypes( sourceType, targetType );
+ DateFormatValidationResult result = dateFormatValidator.validate( "YYYY" );
+ assertThat( result.isValid() ).isTrue();
+ }
+
+ private Type typeWithFQN(String fullQualifiedName) {
+ return new Type(
+ null,
+ null,
+ voidTypeMirror,
+ null,
+ null,
+ null,
+ null,
+ null,
+ fullQualifiedName,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false );
+ }
+
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/model/common/DefaultConversionContextTest.java b/processor/src/test/java/org/mapstruct/ap/model/common/DefaultConversionContextTest.java
new file mode 100755
index 000000000..2bef26c73
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/model/common/DefaultConversionContextTest.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.model.common;
+
+import org.junit.Test;
+import org.mapstruct.ap.testutil.IssueKey;
+import org.mapstruct.ap.util.JavaTimeConstants;
+
+import javax.annotation.processing.Messager;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.tools.Diagnostic;
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * Testing DefaultConversionContext for dateFormat
+ *
+ * @author Timo Eckhardt
+ */
+@IssueKey( "224" )
+public class DefaultConversionContextTest {
+
+ private TypeMirror voidTypeMirror = new TypeMirror() {
+
+ @Override
+ public List extends AnnotationMirror> getAnnotationMirrors() {
+ return null;
+ }
+
+ @Override
+ public A getAnnotation(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ public A[] getAnnotationsByType(Class annotationType) {
+ return null;
+ }
+
+ @Override
+ public TypeKind getKind() {
+ return TypeKind.VOID;
+ }
+
+ @Override
+ public R accept(TypeVisitor v, P p) {
+ return null;
+ }
+ };
+
+ @Test
+ public void testInvalidDateFormatValidation() {
+ Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN );
+ StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock();
+ new DefaultConversionContext(
+ null, statefulMessagerMock, type, type, "qwertz" );
+ assertThat( statefulMessagerMock.getLastKindPrinted() ).isEqualTo( Diagnostic.Kind.ERROR );
+ }
+
+ @Test
+ public void testNullDateFormatValidation() {
+ Type type = typeWithFQN( JavaTimeConstants.ZONED_DATE_TIME_FQN );
+ StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock();
+ new DefaultConversionContext(
+ null, statefulMessagerMock, type, type, null );
+ assertThat( statefulMessagerMock.getLastKindPrinted() ).isNull();
+ }
+
+ @Test
+ public void testUnsupportedType() {
+ Type type = typeWithFQN( "java.lang.String" );
+ StatefulMessagerMock statefulMessagerMock = new StatefulMessagerMock();
+ new DefaultConversionContext(
+ null, statefulMessagerMock, type, type, "qwertz" );
+ assertThat( statefulMessagerMock.getLastKindPrinted() ).isNull();
+ }
+
+ private Type typeWithFQN(String fullQualifiedName) {
+ return new Type(
+ null,
+ null,
+ voidTypeMirror,
+ null,
+ null,
+ null,
+ null,
+ null,
+ fullQualifiedName,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false );
+ }
+
+ private static class StatefulMessagerMock implements Messager {
+
+ private Diagnostic.Kind lastKindPrinted;
+
+ @Override
+ public void printMessage(Diagnostic.Kind kind, CharSequence msg) {
+ lastKindPrinted = kind;
+ }
+
+ @Override
+ public void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e) {
+ }
+
+ @Override
+ public void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a) {
+ }
+
+ @Override
+ public void printMessage(Diagnostic.Kind kind, CharSequence msg, Element e, AnnotationMirror a,
+ AnnotationValue v) {
+ }
+
+ public Diagnostic.Kind getLastKindPrinted() {
+ return lastKindPrinted;
+ }
+
+ }
+}