diff --git a/core-common/src/main/java/org/mapstruct/IterableMapping.java b/core-common/src/main/java/org/mapstruct/IterableMapping.java index 6090087b8..eae77ca4e 100644 --- a/core-common/src/main/java/org/mapstruct/IterableMapping.java +++ b/core-common/src/main/java/org/mapstruct/IterableMapping.java @@ -18,6 +18,7 @@ */ package org.mapstruct; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -41,4 +42,14 @@ public @interface IterableMapping { * @return A date format string as processable by {@link SimpleDateFormat}. */ String dateFormat(); + + /** + * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple + * mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. + * + * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. + * + * @return the qualifiers + */ + Class[] qualifiedBy() default { }; } diff --git a/core-common/src/main/java/org/mapstruct/MapMapping.java b/core-common/src/main/java/org/mapstruct/MapMapping.java index 6fe978a6e..941f1c674 100644 --- a/core-common/src/main/java/org/mapstruct/MapMapping.java +++ b/core-common/src/main/java/org/mapstruct/MapMapping.java @@ -18,6 +18,7 @@ */ package org.mapstruct; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -50,4 +51,26 @@ public @interface MapMapping { * @return A date format string as processable by {@link SimpleDateFormat}. */ String valueDateFormat() default ""; + + /** + * A key value qualifier can be specified to aid the selection process of a suitable mapper. This is useful in + * case multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' + * error. + * + * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. + * + * @return the qualifiers + */ + Class[] keyQualifiedBy() default { }; + + + /** + * A value qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case + * multiple mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. + * + * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. + * + * @return the qualifiers + */ + Class[] valueQualifiedBy() default { }; } diff --git a/core-common/src/main/java/org/mapstruct/Qualifier.java b/core-common/src/main/java/org/mapstruct/Qualifier.java new file mode 100644 index 000000000..65d7d2b2b --- /dev/null +++ b/core-common/src/main/java/org/mapstruct/Qualifier.java @@ -0,0 +1,52 @@ +/** + * 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; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Declares a target annotation to be a qualifier. + * + *

+ * For more info see: + *

    + *
  1. {@link Mapping#qualifiedBy() }
  2. + *
  3. {@link IterableMapping#qualifiedBy() }
  4. + *
  5. {@link MapMapping#keyQualifiedBy() }
  6. + *
  7. {@link MapMapping#valueQualifiedBy() }
  8. + *

    + *

    + * + * @Qualifier + * @Target(ElementType.METHOD) + * @Retention(RetentionPolicy.SOURCE) + * public @interface EnglishToGerman { + * } + * + *

    + * + * @author Sjaak Derksen + */ +@Target(ElementType.ANNOTATION_TYPE) +@Retention(RetentionPolicy.CLASS) +public @interface Qualifier { +} diff --git a/core-jdk8/src/main/java/org/mapstruct/Mapping.java b/core-jdk8/src/main/java/org/mapstruct/Mapping.java index 225d8ea44..d1c06e8b1 100644 --- a/core-jdk8/src/main/java/org/mapstruct/Mapping.java +++ b/core-jdk8/src/main/java/org/mapstruct/Mapping.java @@ -18,6 +18,7 @@ */ package org.mapstruct; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; @@ -31,9 +32,9 @@ import java.util.Date; * * @author Gunnar Morling */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -@Repeatable(Mappings.class) +@Retention( RetentionPolicy.SOURCE ) +@Target( ElementType.METHOD ) +@Repeatable( Mappings.class ) public @interface Mapping { /** @@ -42,8 +43,8 @@ public @interface Mapping { *
  9. The source name of the configured property as defined by the JavaBeans specification.
  10. *
  11. When used to map an enum constant, the name of the constant member is to be given.
  12. *
- * Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping, - * but not two at the same time. If this attribute is given, the target property must be specified via + * Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping, but + * not two at the same time. If this attribute is given, the target property must be specified via * {@link #target()}. * * @return The source name of the configured property or enum constant. @@ -67,13 +68,12 @@ public @interface Mapping { String dateFormat() default ""; /** - * A constant {@link String} based on which the specified target property is to be set. If the designated - * target property is not of type {@code String}, the value will be converted by applying a matching conversion - * method or built-in conversion. + * A constant {@link String} based on which the specified target property is to be set. If the designated target + * property is not of type {@code String}, the value will be converted by applying a matching conversion method or + * built-in conversion. *

- * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, - * but not two at the same time. If this attribute is given, the target property must be specified via - * {@link #target()}. + * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, but not + * two at the same time. If this attribute is given, the target property must be specified via {@link #target()}. * * @return A constant {@code String} constant specifying the value for the designated target property */ @@ -86,9 +86,8 @@ public @interface Mapping { * {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java * expression in the designated {@link #target()} property. *

- * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping, - * but not two at the same time. If this attribute is given, the target property must be specified via - * {@link #target()}. + * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping, but not + * two at the same time. If this attribute is given, the target property must be specified via {@link #target()}. * * @return A constant {@code String} constant specifying the value for the designated target property */ @@ -103,4 +102,14 @@ public @interface Mapping { * @return {@code true} if the given property should be ignored, {@code false} otherwise */ boolean ignore() default false; + + /** + * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple + * mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. + * + * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. + * + * @return the qualifiers + */ + Class[] qualifiedBy() default { }; } diff --git a/core/src/main/java/org/mapstruct/Mapping.java b/core/src/main/java/org/mapstruct/Mapping.java index 48d4583f0..56e0e9623 100644 --- a/core/src/main/java/org/mapstruct/Mapping.java +++ b/core/src/main/java/org/mapstruct/Mapping.java @@ -18,6 +18,7 @@ */ package org.mapstruct; +import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -101,4 +102,14 @@ public @interface Mapping { * @return {@code true} if the given property should be ignored, {@code false} otherwise */ boolean ignore() default false; + + /** + * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple + * mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. + * + * A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method. + * + * @return the qualifiers + */ + Class[] qualifiedBy() default { }; } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java index 1e2ee91e6..6381926ba 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/IterableMapping.java @@ -18,8 +18,10 @@ */ package org.mapstruct.ap.model.source; +import java.util.List; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; +import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.prism.IterableMappingPrism; @@ -31,6 +33,7 @@ import org.mapstruct.ap.prism.IterableMappingPrism; public class IterableMapping { private final String dateFormat; + private final List qualifiers; private final AnnotationMirror mirror; private final AnnotationValue dateFormatAnnotationValue; @@ -41,13 +44,19 @@ public class IterableMapping { return new IterableMapping( iterableMapping.dateFormat(), + iterableMapping.qualifiedBy(), iterableMapping.mirror, iterableMapping.values.dateFormat() ); } - private IterableMapping(String dateFormat, AnnotationMirror mirror, AnnotationValue dateFormatAnnotationValue) { + private IterableMapping( + String dateFormat, + List qualifiers, + AnnotationMirror mirror, + AnnotationValue dateFormatAnnotationValue) { this.dateFormat = dateFormat; + this.qualifiers = qualifiers; this.mirror = mirror; this.dateFormatAnnotationValue = dateFormatAnnotationValue; } @@ -56,6 +65,10 @@ public class IterableMapping { return dateFormat; } + public List getQualifiers() { + return qualifiers; + } + public AnnotationMirror getMirror() { return mirror; } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java index 48bfdd873..8552a93ab 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/MapMapping.java @@ -18,7 +18,9 @@ */ package org.mapstruct.ap.model.source; +import java.util.List; import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.prism.MapMappingPrism; @@ -30,7 +32,9 @@ import org.mapstruct.ap.prism.MapMappingPrism; public class MapMapping { private final String keyFormat; + private final List keyQualifiers; private final String valueFormat; + private final List valueQualifiers; private final AnnotationMirror mirror; public static MapMapping fromPrism(MapMappingPrism mapMapping) { @@ -40,14 +44,23 @@ public class MapMapping { return new MapMapping( mapMapping.keyDateFormat(), + mapMapping.keyQualifiedBy(), mapMapping.valueDateFormat(), + mapMapping.valueQualifiedBy(), mapMapping.mirror ); } - private MapMapping(String keyFormat, String valueFormat, AnnotationMirror mirror) { + private MapMapping( + String keyFormat, + List keyQualifiers, + String valueFormat, + List valueQualifiers, + AnnotationMirror mirror) { this.keyFormat = keyFormat; + this.keyQualifiers = keyQualifiers; this.valueFormat = valueFormat; + this.valueQualifiers = valueQualifiers; this.mirror = mirror; } @@ -55,10 +68,18 @@ public class MapMapping { return keyFormat; } + public List getKeyQualifiers() { + return keyQualifiers; + } + public String getValueFormat() { return valueFormat; } + public List getValueQualifiers() { + return valueQualifiers; + } + public AnnotationMirror getMirror() { return mirror; } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java index 64a12fbc5..45deaf4ae 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/Mapping.java @@ -29,6 +29,7 @@ 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.TypeMirror; import javax.tools.Diagnostic; import org.mapstruct.ap.prism.MappingPrism; @@ -52,6 +53,7 @@ public class Mapping { private final String javaExpression; private final String targetName; private final String dateFormat; + private final List qualifiers; private final boolean isIgnored; private final AnnotationMirror mirror; private final AnnotationValue sourceAnnotationValue; @@ -126,6 +128,7 @@ public class Mapping { mappingPrism.expression(), mappingPrism.target(), mappingPrism.dateFormat(), + mappingPrism.qualifiedBy(), mappingPrism.ignore(), mappingPrism.mirror, mappingPrism.values.source(), @@ -153,9 +156,10 @@ public class Mapping { } //CHECKSTYLE:OFF - private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String constant, - String expression, String targetName, String dateFormat, boolean isIgnored, AnnotationMirror mirror, - AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue) { + private Mapping( String sourceName, String sourceParameterName, String sourcePropertyName, String constant, + String expression, String targetName, String dateFormat, List qualifiers, + boolean isIgnored, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue, + AnnotationValue targetAnnotationValue) { this.sourceName = sourceName; this.sourceParameterName = sourceParameterName; this.sourcePropertyName = sourcePropertyName; @@ -165,6 +169,7 @@ public class Mapping { this.javaExpression = javaExpressionMatcher.matches() ? javaExpressionMatcher.group( 1 ).trim() : ""; this.targetName = targetName.equals( "" ) ? sourceName : targetName; this.dateFormat = dateFormat; + this.qualifiers = qualifiers; this.isIgnored = isIgnored; this.mirror = mirror; this.sourceAnnotationValue = sourceAnnotationValue; @@ -216,6 +221,10 @@ public class Mapping { return dateFormat; } + public List getQualifiers() { + return qualifiers; + } + public boolean isIgnored() { return isIgnored; } @@ -244,6 +253,7 @@ public class Mapping { expression, sourceName, dateFormat, + qualifiers, isIgnored, mirror, sourceAnnotationValue, diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/InheritanceSelector.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/InheritanceSelector.java index 4f31e86ba..7e9cebcd8 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/selector/InheritanceSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/InheritanceSelector.java @@ -20,6 +20,7 @@ package org.mapstruct.ap.model.source.selector; import java.util.ArrayList; import java.util.List; +import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Type; @@ -33,8 +34,14 @@ import org.mapstruct.ap.model.source.Method; public class InheritanceSelector implements MethodSelector { @Override - public List getMatchingMethods(Method mappingMethod, List methods, Type parameterType, - Type returnType, String targetPropertyName) { + public List getMatchingMethods( + Method mappingMethod, + List methods, + Type parameterType, + Type returnType, + List qualifiers, + String targetPropertyName + ) { List candidatesWithBestMatchingSourceType = new ArrayList(); int bestMatchingSourceTypeDistance = Integer.MAX_VALUE; diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelector.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelector.java index 2fb494da5..f939d1747 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelector.java @@ -19,6 +19,7 @@ package org.mapstruct.ap.model.source.selector; import java.util.List; +import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.source.Method; @@ -40,10 +41,12 @@ public interface MethodSelector { * @param methods list of available methods * @param parameterType parameter type that should be matched * @param returnType return type that should be matched + * @param qualifiers list of custom annotations, used in the qualifying process * @param targetPropertyName some information can be derived from the target property * * @return list of methods that passes the matching process */ List getMatchingMethods(Method mappingMethod, List methods, Type parameterType, - Type returnType, String targetPropertyName); + Type returnType, List qualifiers, + String targetPropertyName); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelectors.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelectors.java index ecd352c21..f95bfe396 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelectors.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/MethodSelectors.java @@ -21,6 +21,8 @@ package org.mapstruct.ap.model.source.selector; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import org.mapstruct.ap.model.common.Parameter; @@ -37,18 +39,21 @@ public class MethodSelectors implements MethodSelector { private final List selectors; - public MethodSelectors(Types typeUtils, TypeFactory typeFactory) { + public MethodSelectors(Types typeUtils, Elements elementUtils, TypeFactory typeFactory) { selectors = Arrays.asList( new TypeSelector( typeFactory ), new InheritanceSelector(), - new XmlElementDeclSelector( typeUtils ) + new XmlElementDeclSelector( typeUtils ), + new QualifierSelector( typeUtils, elementUtils ) ); } @Override - public List getMatchingMethods(Method mappingMethod, List methods, Type parameterType, - Type returnType, String targetPropertyName) { + public List getMatchingMethods(Method mappingMethod, List methods, + Type parameterType, Type returnType, + List qualifiers, + String targetPropertyName) { List candidates = new ArrayList( methods ); @@ -58,6 +63,7 @@ public class MethodSelectors implements MethodSelector { candidates, parameterType, returnType, + qualifiers, targetPropertyName ); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/QualifierSelector.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/QualifierSelector.java new file mode 100644 index 000000000..3c4beb05a --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/QualifierSelector.java @@ -0,0 +1,125 @@ +/** + * 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.source.selector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; +import org.mapstruct.Qualifier; +import org.mapstruct.ap.model.common.Type; +import org.mapstruct.ap.model.source.Method; +import org.mapstruct.ap.model.source.SourceMethod; + +/** + * This selector selects a best match based on qualifiers name. + * + * @author Sjaak Derksen + */ +public class QualifierSelector implements MethodSelector { + + private final Types typeUtils; + private final TypeMirror qualifierType; + + + public QualifierSelector( Types typeUtils, Elements elementUtils ) { + this.typeUtils = typeUtils; + qualifierType = elementUtils.getTypeElement( Qualifier.class.getCanonicalName() ).asType(); + } + + @Override + public List getMatchingMethods(Method mappingMethod, List methods, + Type parameterType, Type returnType, + List qualifiers, + String targetPropertyName) { + List matches = new ArrayList(); + + if ( qualifiers == null || qualifiers.isEmpty() ) { + return methods; + } + + for ( T candidate : methods ) { + + if ( !( candidate instanceof SourceMethod ) ) { + continue; + } + + // retrieve annotations + Set combinedAnnotations = new HashSet(); + + // first from the method itself + SourceMethod candidateSM = (SourceMethod) candidate; + List methodAnnotations = candidateSM.getExecutable().getAnnotationMirrors(); + for ( AnnotationMirror methodAnnotation : methodAnnotations ) { + addOnlyWhenQualifier( combinedAnnotations, methodAnnotation ); + } + + // then from the mapper (if declared) + Type mapper = candidate.getDeclaringMapper(); + if ( mapper != null ) { + List mapperAnnotations = mapper.getTypeElement().getAnnotationMirrors(); + for ( AnnotationMirror mapperAnnotation : mapperAnnotations ) { + addOnlyWhenQualifier( combinedAnnotations, mapperAnnotation ); + } + } + + // now count if all qualifiers are machted + int matchingQualifierCounter = 0; + for ( TypeMirror qualifier : qualifiers) { + for ( TypeMirror annotationType : combinedAnnotations ) { + if ( typeUtils.isSameType( qualifier, annotationType ) ) { + matchingQualifierCounter++; + break; + } + } + } + + if ( matchingQualifierCounter == qualifiers.size() ) { + // all qualifiers are matched with a qualifying annotation, add candidate + matches.add( candidate ); + } + } + if ( !matches.isEmpty() ) { + return matches; + } + else { + return methods; + } + } + + private void addOnlyWhenQualifier( Set annotationSet, AnnotationMirror candidate ) { + + // get all the annotations of the candidate annotation + List annotationsOfCandidate + = candidate.getAnnotationType().asElement().getAnnotationMirrors(); + + // only add the candidate annotation when the candidate itself has the annotation 'Qualifier' + for ( AnnotationMirror annotationOfCandidate : annotationsOfCandidate ) { + if ( typeUtils.isSameType( annotationOfCandidate.getAnnotationType(), qualifierType ) ) { + annotationSet.add( candidate.getAnnotationType() ); + break; + } + } + } +} + diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/TypeSelector.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/TypeSelector.java index 6d7504f4d..1ae06ac81 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/selector/TypeSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/TypeSelector.java @@ -20,6 +20,7 @@ package org.mapstruct.ap.model.source.selector; import java.util.ArrayList; import java.util.List; +import javax.lang.model.type.TypeMirror; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.TypeFactory; @@ -41,8 +42,10 @@ public class TypeSelector implements MethodSelector { } @Override - public List getMatchingMethods(Method mappingMethod, List methods, Type parameterType, - Type returnType, String targetPropertyName) { + public List getMatchingMethods(Method mappingMethod, List methods, + Type parameterType, Type returnType, + List qualifiers, + String targetPropertyName) { List result = new ArrayList(); for ( T method : methods ) { diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/selector/XmlElementDeclSelector.java b/processor/src/main/java/org/mapstruct/ap/model/source/selector/XmlElementDeclSelector.java index 479b94abb..6ba689ed9 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/selector/XmlElementDeclSelector.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/selector/XmlElementDeclSelector.java @@ -51,13 +51,16 @@ public class XmlElementDeclSelector implements MethodSelector { } @Override - public List getMatchingMethods(Method mappingMethod, List methods, Type parameterType, - Type returnType, String targetPropertyName) { + public List getMatchingMethods(Method mappingMethod, List methods, + Type parameterType, Type returnType, + List qualifiers, + String targetPropertyName) { // only true source methods are qualifying if ( !(mappingMethod instanceof SourceMethod) ) { return methods; } + SourceMethod sourceMappingMethod = (SourceMethod) mappingMethod; List nameMatches = new ArrayList(); diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index e4e4bd146..b4cf61f2b 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -297,11 +297,21 @@ public class MapperCreationProcessor implements ModelElementProcessor qualifiers = null; + if ( method.getIterableMapping() != null ) { + dateFormat = method.getIterableMapping().getDateFormat(); + qualifiers = method.getIterableMapping().getQualifiers(); + } + + IterableMappingMethod iterableMappingMethod = getIterableMappingMethod( + mapperReferences, + methods, + method, + dateFormat, + qualifiers + ); hasFactoryMethod = iterableMappingMethod.getFactoryMethod() != null; mappingMethods.add( iterableMappingMethod ); } @@ -312,13 +322,24 @@ public class MapperCreationProcessor implements ModelElementProcessor keyQualifiers = null; + List valueQualifiers = null; if ( method.getMapMapping() != null ) { keyDateFormat = method.getMapMapping().getKeyFormat(); valueDateFormat = method.getMapMapping().getValueFormat(); + keyQualifiers = method.getMapMapping().getKeyQualifiers(); + valueQualifiers = method.getMapMapping().getValueQualifiers(); } - MapMappingMethod mapMappingMethod - = getMapMappingMethod( mapperReferences, methods, method, keyDateFormat, valueDateFormat ); + MapMappingMethod mapMappingMethod = getMapMappingMethod( + mapperReferences, + methods, + method, + keyDateFormat, + valueDateFormat, + keyQualifiers, + valueQualifiers + ); hasFactoryMethod = mapMappingMethod.getFactoryMethod() != null; mappingMethods.add( mapMappingMethod ); } @@ -438,9 +459,11 @@ public class MapperCreationProcessor implements ModelElementProcessor qualifiers = null; String sourcePropertyName; if ( mapping != null ) { dateFormat = mapping.getDateFormat(); + qualifiers = mapping.getQualifiers(); sourcePropertyName = mapping.getSourcePropertyName(); } else { @@ -466,7 +489,8 @@ public class MapperCreationProcessor implements ModelElementProcessor qualifiers) { Type sourceType; Type targetType; @@ -815,6 +842,7 @@ public class MapperCreationProcessor implements ModelElementProcessor qualifiers) { // source String mappedElement = "constant '" + constantExpression + "'"; @@ -944,6 +973,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, List methods, Method method, - String dateFormat ) { + String dateFormat, + List qualifiers) { Type sourceElementType = method.getSourceParameters().iterator().next().getType().getTypeParameters().get( 0 ); Type targetElementType = method.getResultType().getTypeParameters().get( 0 ); String conversionStr = Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() ); @@ -1000,6 +1031,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, List methods, - Method method, String keyDateFormat, String valueDateFormat ) { + private MapMappingMethod getMapMappingMethod(List mapperReferences, + List methods, + Method method, + String keyDateFormat, + String valueDateFormat, + List keyQualifiers, + List valueQualifiers ) { List sourceTypeParams = method.getSourceParameters().iterator().next().getType().getTypeParameters(); List resultTypeParams = method.getResultType().getTypeParameters(); @@ -1037,6 +1074,7 @@ public class MapperCreationProcessor implements ModelElementProcessor(); - this.methodSelectors = new MethodSelectors( typeUtils, typeFactory ); + this.methodSelectors = new MethodSelectors( typeUtils, elementUtils, typeFactory ); this.typeUtils = typeUtils; } @@ -105,6 +105,7 @@ public class MappingResolver { * @param targetType return type to match * @param targetPropertyName name of the target property * @param dateFormat used for formatting dates in build in methods that need context information + * @param qualifiers used for further select the appropriate mapping method based on class and name * @param sourceReference call to source type as string * * @return an assignment to a method parameter, which can either be: @@ -123,6 +124,7 @@ public class MappingResolver { Type targetType, String targetPropertyName, String dateFormat, + List qualifiers, String sourceReference ) { ResolvingAttempt attempt = new ResolvingAttempt( mappingMethod, @@ -131,6 +133,7 @@ public class MappingResolver { methods, targetPropertyName, dateFormat, + qualifiers, sourceReference, this ); @@ -151,6 +154,7 @@ public class MappingResolver { private final List methods; private final String targetPropertyName; private final String dateFormat; + private final List qualifiers; private final String sourceReference; private final MappingResolver context; @@ -165,6 +169,7 @@ public class MappingResolver { List methods, String targetPropertyName, String dateFormat, + List qualifiers, String sourceReference, MappingResolver context ) { this.mappingMethod = mappingMethod; @@ -173,6 +178,7 @@ public class MappingResolver { this.methods = methods; this.targetPropertyName = targetPropertyName; this.dateFormat = dateFormat; + this.qualifiers = qualifiers; this.sourceReference = sourceReference; this.context = context; this.virtualMethodCandidates = new HashSet(); @@ -403,6 +409,7 @@ public class MappingResolver { methods, sourceType, returnType, + qualifiers, targetPropertyName ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/ErroneousMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/ErroneousMapper.java new file mode 100644 index 000000000..7cef559a0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/ErroneousMapper.java @@ -0,0 +1,44 @@ +/** + * 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.selection.qualifier; + +import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease; +import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated; +import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; +import org.mapstruct.ap.test.selection.qualifier.handwritten.YetAnotherMapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = { SomeOtherMapper.class, YetAnotherMapper.class } ) +public interface ErroneousMapper { + + ErroneousMapper INSTANCE = Mappers.getMapper( ErroneousMapper.class ); + + @Mappings( { + @Mapping( source = "title", qualifiedBy = { NonQualifierAnnotated.class } ), } ) + GermanRelease toGerman( OriginalRelease movies ); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/FactMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/FactMapper.java new file mode 100644 index 000000000..776820873 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/FactMapper.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.test.selection.qualifier; + +import java.util.List; +import java.util.Map; +import org.mapstruct.MapMapping; +import org.mapstruct.Mapper; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; +import org.mapstruct.ap.test.selection.qualifier.handwritten.Facts; +import org.mapstruct.ap.test.selection.qualifier.handwritten.PlotWords; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = { Facts.class, PlotWords.class } ) +public interface FactMapper { + + FactMapper INSTANCE = Mappers.getMapper( FactMapper.class ); + + @MapMapping( keyQualifiedBy = { EnglishToGerman.class }, valueQualifiedBy = { EnglishToGerman.class } ) + Map> mapFacts( Map> keyWords ); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/KeyWordMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/KeyWordMapper.java new file mode 100644 index 000000000..dbf3a7d02 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/KeyWordMapper.java @@ -0,0 +1,54 @@ +/** + * 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.selection.qualifier; + +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import org.mapstruct.IterableMapping; +import org.mapstruct.Mapper; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; +import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = { SomeOtherMapper.class } ) +public abstract class KeyWordMapper { + + private static final Map EN_GER = ImmutableMap.builder() + .put( "magnificent", "Großartig" ) + .put( "evergreen", "Evergreen" ) + .put( "classic", "Klassiker" ) + .put( "box office flop", "Kasse Flop" ) + .build(); + + + public static final KeyWordMapper INSTANCE = Mappers.getMapper( KeyWordMapper.class ); + + @IterableMapping( dateFormat = "", qualifiedBy = { EnglishToGerman.class } ) + abstract List mapKeyWords( List keyWords ); + + @EnglishToGerman + public String mapKeyWord( String keyword ) { + return EN_GER.get( keyword ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/MovieMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/MovieMapper.java new file mode 100644 index 000000000..bf1bc9b61 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/MovieMapper.java @@ -0,0 +1,46 @@ +/** + * 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.selection.qualifier; + +import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease; +import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease; +import org.mapstruct.ap.test.selection.qualifier.handwritten.Titles; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; +import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; +import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = { Titles.class, SomeOtherMapper.class, KeyWordMapper.class, FactMapper.class } ) +public interface MovieMapper { + + MovieMapper INSTANCE = Mappers.getMapper( MovieMapper.class ); + + @Mappings( { + @Mapping( source = "title", qualifiedBy = { TitleTranslator.class, EnglishToGerman.class } ), + } ) + GermanRelease toGerman( OriginalRelease movies ); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java new file mode 100644 index 000000000..a54d871e0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/QualifierTest.java @@ -0,0 +1,119 @@ +/** + * 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.selection.qualifier; + +import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease; +import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease; +import org.mapstruct.ap.test.selection.qualifier.bean.AbstractEntry; +import org.mapstruct.ap.test.selection.qualifier.handwritten.Titles; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.tools.Diagnostic.Kind; +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; +import org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated; +import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; +import org.mapstruct.ap.test.selection.qualifier.handwritten.Facts; +import org.mapstruct.ap.test.selection.qualifier.handwritten.PlotWords; +import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; +import org.mapstruct.ap.test.selection.qualifier.handwritten.YetAnotherMapper; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; +import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * + * @author Sjaak Derksen + */ +@IssueKey( "268" ) +@WithClasses( { + OriginalRelease.class, + GermanRelease.class, + AbstractEntry.class, + SomeOtherMapper.class, + NonQualifierAnnotated.class +} ) +@RunWith( AnnotationProcessorTestRunner.class ) +public class QualifierTest { + + @Test + @WithClasses( { + Titles.class, + Facts.class, + PlotWords.class, + OriginalRelease.class, + EnglishToGerman.class, + TitleTranslator.class, + MovieMapper.class, + KeyWordMapper.class, + FactMapper.class } ) + public void shouldMatchClassAndMethod() { + + OriginalRelease foreignMovies = new OriginalRelease(); + foreignMovies.setTitle( "Sixth Sense, The" ); + foreignMovies.setKeyWords( Arrays.asList( "evergreen", "magnificent" ) ); + Map> facts = new HashMap>(); + facts.put( "director", Arrays.asList( "M. Night Shyamalan" ) ); + facts.put( "cast", Arrays.asList( "Bruce Willis", "Haley Joel Osment", "Toni Collette" ) ); + facts.put( "plot keywords", Arrays.asList( "boy", "child psychologist", "I see dead people" ) ); + foreignMovies.setFacts( facts ); + + GermanRelease germanMovies = MovieMapper.INSTANCE.toGerman( foreignMovies ); + assertThat( germanMovies ).isNotNull(); + assertThat( germanMovies.getTitle() ).isEqualTo( "Der sechste Sinn" ); + assertThat( germanMovies.getKeyWords() ).isNotNull(); + assertThat( germanMovies.getKeyWords().size() ).isEqualTo( 2 ); + assertThat( germanMovies.getKeyWords() ).containsSequence( "Evergreen", "Großartig" ); + + assertThat( germanMovies.getFacts() ).isNotNull(); + assertThat( germanMovies.getFacts() ).hasSize( 3 ); + assertThat( germanMovies.getFacts() ).includes( + entry( "Regisseur", Arrays.asList( "M. Night Shyamalan" ) ), + entry( "Besetzung", Arrays.asList( "Bruce Willis", "Haley Joel Osment", "Toni Collette" ) ), + entry( "Handlungstichwörter", Arrays.asList( "Jungen", "Kinderpsychologe", "Ich sehe tote Menschen" ) ) + ); + } + + @Test + @WithClasses( { + YetAnotherMapper.class, + ErroneousMapper.class + } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = ErroneousMapper.class, + kind = Kind.ERROR, + line = 42, + messageRegExp = "Ambiguous mapping methods found for mapping property 'title' " + + "from java.lang.String to java.lang.String.*" ) + } + ) + public void shouldNotProduceMatchingMethod() { + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/EnglishToGerman.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/EnglishToGerman.java new file mode 100644 index 000000000..853a3bf9d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/EnglishToGerman.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.test.selection.qualifier.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.mapstruct.Qualifier; + +/** + * + * @author Sjaak Derksen + */ +@Qualifier +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface EnglishToGerman { +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/NonQualifierAnnotated.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/NonQualifierAnnotated.java new file mode 100644 index 000000000..e5673d9fb --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/NonQualifierAnnotated.java @@ -0,0 +1,33 @@ +/** + * 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.selection.qualifier.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Sjaak Derksen + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface NonQualifierAnnotated { +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/TitleTranslator.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/TitleTranslator.java new file mode 100644 index 000000000..b4f59175a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/annotation/TitleTranslator.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.test.selection.qualifier.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.mapstruct.Qualifier; + +/** + * + * @author Sjaak Derksen + */ +@Qualifier +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface TitleTranslator { +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/AbstractEntry.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/AbstractEntry.java new file mode 100644 index 000000000..661f63411 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/AbstractEntry.java @@ -0,0 +1,61 @@ +/** + * 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.selection.qualifier.bean; + +import java.util.List; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public abstract class AbstractEntry { + + private String title; + + private List keyWords; + + private Map> facts; + + public String getTitle() { + return title; + } + + public void setTitle( String title ) { + this.title = title; + } + + public List getKeyWords() { + return keyWords; + } + + public void setKeyWords( List keyWords ) { + this.keyWords = keyWords; + } + + public Map > getFacts() { + return facts; + } + + public void setFacts( Map > facts ) { + this.facts = facts; + } + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/GermanRelease.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/GermanRelease.java new file mode 100644 index 000000000..7088fcbe4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/GermanRelease.java @@ -0,0 +1,27 @@ +/** + * 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.selection.qualifier.bean; + +/** + * + * @author Sjaak Derksen + */ +public class GermanRelease extends AbstractEntry { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/OriginalRelease.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/OriginalRelease.java new file mode 100644 index 000000000..180a86f5f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/bean/OriginalRelease.java @@ -0,0 +1,27 @@ +/** + * 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.selection.qualifier.bean; + +/** + * + * @author Sjaak Derksen + */ +public class OriginalRelease extends AbstractEntry { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Facts.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Facts.java new file mode 100644 index 000000000..9e2f6b27e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Facts.java @@ -0,0 +1,45 @@ +/** + * 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.selection.qualifier.handwritten; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; + +/** + * + * @author Sjaak Derksen + */ +public class Facts { + + private static final Map EN_GER = ImmutableMap.builder() + .put( "director", "Regisseur" ) + .put( "cast", "Besetzung" ) + .put( "cameo", "Kurzauftritt" ) + .put( "soundtrack", "Filmmusik" ) + .put( "plot keywords", "Handlungstichwörter" ) + .build(); + + @EnglishToGerman + public String translateFactName( String fact ) { + String result = EN_GER.get( fact ); + return result != null ? result : fact; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/PlotWords.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/PlotWords.java new file mode 100644 index 000000000..e42834495 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/PlotWords.java @@ -0,0 +1,57 @@ +/** + * 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.selection.qualifier.handwritten; + +import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; + +/** + * + * @author Sjaak Derksen + */ +public class PlotWords { + + private static final Map EN_GER = ImmutableMap.builder() + .put( "boy", "Jungen" ) + .put( "child psychologist", "Kinderpsychologe" ) + .put( "I see dead people", "Ich sehe tote Menschen" ) + .build(); + + @EnglishToGerman + public List translate( List keywords ) { + List result = new ArrayList(); + for ( String keyword : keywords ) { + if ( EN_GER.containsKey( keyword ) ) { + result.add( EN_GER.get( keyword ) ); + } + else { + result.add( keyword ); + } + } + return result; + } + + public List methodNotToSelect( List title ) { + throw new AssertionError( "method should not be called" ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/SomeOtherMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/SomeOtherMapper.java new file mode 100644 index 000000000..4adf6ca9d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/SomeOtherMapper.java @@ -0,0 +1,33 @@ +/** + * 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.selection.qualifier.handwritten; + +import org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated; + +/** + * + * @author Sjaak Derksen + */ +public class SomeOtherMapper { + + @NonQualifierAnnotated + public String methodNotToSelect( String title ) { + throw new AssertionError( "method should not be called" ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Titles.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Titles.java new file mode 100644 index 000000000..f3e0d71ba --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/Titles.java @@ -0,0 +1,52 @@ +/** + * 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.selection.qualifier.handwritten; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; +import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; +//import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; + +/** + * + * @author Sjaak Derksen + */ +@TitleTranslator +public class Titles { + + private static final Map EN_GER = ImmutableMap.builder() + .put( "Star Wars", "Krieg der Sterne" ) + .put( "Sixth Sense, The", "Der sechste Sinn" ) + .put( "Shawshank Redemption, The", "Die Verurteilten" ) + .put( "Trainspotting", "Neue Helden" ) + .put( "Never Say Never", "Sag niemals nie" ) + .build(); + + @EnglishToGerman + public String translateTitle(String title) { + return EN_GER.get( title ); + } + + + public String methodNotToSelect( String title ) { + throw new AssertionError( "method should not be called" ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/YetAnotherMapper.java b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/YetAnotherMapper.java new file mode 100644 index 000000000..0aea924e2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/selection/qualifier/handwritten/YetAnotherMapper.java @@ -0,0 +1,30 @@ +/** + * 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.selection.qualifier.handwritten; + +/** + * + * @author Sjaak Derksen + */ +public class YetAnotherMapper { + + public String methodNotToSelect( String title ) { + throw new AssertionError( "method should not be called" ); + } +}