From acfca6235d9f4bf581adc7a5f36b7035765d6444 Mon Sep 17 00:00:00 2001 From: sjaakd Date: Thu, 19 Jun 2014 21:42:02 +0200 Subject: [PATCH] #207 adder method support for target collections and unit test --- .../mapstruct/CollectionMappingStrategy.java | 52 +++++ .../src/main/java/org/mapstruct/Mapper.java | 8 + .../main/java/org/mapstruct/MapperConfig.java | 8 + .../src/main/java/org/mapstruct/Mapping.java | 1 + core/src/main/java/org/mapstruct/Mapping.java | 1 + .../ap/model/assignment/AdderWrapper.java | 75 ++++++ .../org/mapstruct/ap/model/common/Type.java | 87 ++++++- .../mapstruct/ap/model/source/Mapping.java | 1 + .../ap/processor/MapperCreationProcessor.java | 151 ++++++++---- .../org/mapstruct/ap/util/Executables.java | 40 ++++ .../java/org/mapstruct/ap/util/Filters.java | 12 + .../org/mapstruct/ap/util/MapperConfig.java | 24 +- .../java/org/mapstruct/ap/util/Nouns.java | 143 ++++++++++++ .../java/org/mapstruct/ap/util/Strings.java | 115 ++++----- ...truct.ap.model.assignment.AdderWrapper.ftl | 46 ++++ .../ap/test/collection/adder/AdderTest.java | 221 ++++++++++++++++++ .../test/collection/adder/CatException.java | 33 +++ .../test/collection/adder/DogException.java | 33 +++ .../ap/test/collection/adder/PetMapper.java | 99 ++++++++ .../collection/adder/SourceTargetMapper.java | 55 +++++ .../SourceTargetMapperStrategyDefault.java | 37 +++ ...ceTargetMapperStrategySetterPreferred.java | 41 ++++ .../ap/test/collection/adder/TeethMapper.java | 38 +++ .../test/collection/adder/source/Source.java | 38 +++ .../collection/adder/source/SourceTeeth.java | 38 +++ .../adder/target/AdderUsageObserver.java | 39 ++++ .../collection/adder/target/IndoorPet.java | 43 ++++ .../collection/adder/target/OutdoorPet.java | 43 ++++ .../ap/test/collection/adder/target/Pet.java | 27 +++ .../test/collection/adder/target/Target.java | 59 +++++ .../collection/adder/target/TargetDali.java | 48 ++++ .../collection/adder/target/TargetHuman.java | 54 +++++ .../adder/target/TargetOnlyGetter.java | 55 +++++ .../adder/target/TargetViaTargetType.java | 47 ++++ .../adder/target/TargetWithoutSetter.java | 43 ++++ 35 files changed, 1751 insertions(+), 104 deletions(-) create mode 100644 core-common/src/main/java/org/mapstruct/CollectionMappingStrategy.java create mode 100644 processor/src/main/java/org/mapstruct/ap/model/assignment/AdderWrapper.java create mode 100644 processor/src/main/java/org/mapstruct/ap/util/Nouns.java create mode 100644 processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/CatException.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/DogException.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/PetMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategyDefault.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategySetterPreferred.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/TeethMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceTeeth.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/AdderUsageObserver.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/IndoorPet.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/OutdoorPet.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Pet.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Target.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetDali.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetHuman.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetOnlyGetter.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetViaTargetType.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetWithoutSetter.java diff --git a/core-common/src/main/java/org/mapstruct/CollectionMappingStrategy.java b/core-common/src/main/java/org/mapstruct/CollectionMappingStrategy.java new file mode 100644 index 000000000..8ec484cde --- /dev/null +++ b/core-common/src/main/java/org/mapstruct/CollectionMappingStrategy.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; + +/** + * Strategy for mapping of collections. + * @author Sjaak Derksen + */ +public enum CollectionMappingStrategy { + + /** + * MapStruct will consider setter methods as target as way to access the target. + * + * Note: If no setter is available a getter will be used under the assumption it has been initialized. + */ + SETTER_ONLY, + /** + * MapStruct will consider setter methods as preferred way to access the target. + * + * If no setter is available, MapStruct will first look for an adder method before resorting to a getter. + */ + SETTER_PREFERRED, + /** + * MapStruct will consider adder methods as preferred way to access the target. + * + * If no adder is available, MapStruct will first look for a setter method before resorting to a getter. + */ + ADDER_PREFERRED, + /** + * The default option is: {@link CollectionMappingStrategy#SETTER_ONLY}. + * + * The default options forces deliberate setting in {@link Mapper#collectionMappingStrategy() }, in order + * to override a setting in {@link MapperConfig#collectionMappingStrategy() } + */ + DEFAULT; +} diff --git a/core-common/src/main/java/org/mapstruct/Mapper.java b/core-common/src/main/java/org/mapstruct/Mapper.java index f6703b27d..b1d164fd1 100644 --- a/core-common/src/main/java/org/mapstruct/Mapper.java +++ b/core-common/src/main/java/org/mapstruct/Mapper.java @@ -83,4 +83,12 @@ public @interface Mapper { */ Class config() default void.class; + /** + * When a the target is a collection, look for a suitable adder. If the property is defined as plural, (so + * getItems(), the adder will assumed to be the singular form: addItem() + * + * @return true if the adder should be used. + */ + CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.DEFAULT; + } diff --git a/core-common/src/main/java/org/mapstruct/MapperConfig.java b/core-common/src/main/java/org/mapstruct/MapperConfig.java index 5a4b7bccf..98a413a58 100644 --- a/core-common/src/main/java/org/mapstruct/MapperConfig.java +++ b/core-common/src/main/java/org/mapstruct/MapperConfig.java @@ -72,4 +72,12 @@ public @interface MapperConfig { * @return The component model for the generated mapper. */ String componentModel() default "default"; + + /** + * When a the target is a collection, look for a suitable adder. If the property is defined as plural, (so + * getItems(), the adder will assumed to be the singular form: addItem() + * + * @return true if the adder should be used. + */ + CollectionMappingStrategy collectionMappingStrategy() default CollectionMappingStrategy.DEFAULT; } diff --git a/core-jdk8/src/main/java/org/mapstruct/Mapping.java b/core-jdk8/src/main/java/org/mapstruct/Mapping.java index 22aa0d28b..05e49d3ee 100644 --- a/core-jdk8/src/main/java/org/mapstruct/Mapping.java +++ b/core-jdk8/src/main/java/org/mapstruct/Mapping.java @@ -76,4 +76,5 @@ public @interface Mapping { * @return A constant {@code String} expression specifying the value for the designated target prperty */ String expression() default ""; + } diff --git a/core/src/main/java/org/mapstruct/Mapping.java b/core/src/main/java/org/mapstruct/Mapping.java index 63fed1607..c9f3e7a34 100644 --- a/core/src/main/java/org/mapstruct/Mapping.java +++ b/core/src/main/java/org/mapstruct/Mapping.java @@ -74,4 +74,5 @@ public @interface Mapping { * @return A constant {@code String} expression specifying the value for the designated target prperty */ String expression() default ""; + } diff --git a/processor/src/main/java/org/mapstruct/ap/model/assignment/AdderWrapper.java b/processor/src/main/java/org/mapstruct/ap/model/assignment/AdderWrapper.java new file mode 100644 index 000000000..d696f75d5 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/model/assignment/AdderWrapper.java @@ -0,0 +1,75 @@ +/** + * 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.assignment; + +import java.util.ArrayList; +import java.util.List; +import org.mapstruct.ap.model.Assignment; +import org.mapstruct.ap.model.common.Type; + +/** + * Wraps the assignment in a target setter. + * + * @author Sjaak Derksen + */ +public class AdderWrapper extends AssignmentWrapper { + + private final List exceptionTypesToExclude; + private final String sourceReference; + private final Type sourceType; + + public AdderWrapper( + Assignment decoratedAssignment, + List exceptionTypesToExclude, + String sourceReference, + Type sourceType) { + super( decoratedAssignment ); + this.exceptionTypesToExclude = exceptionTypesToExclude; + this.sourceReference = sourceReference; + this.sourceType = sourceType; + } + + @Override + public List getExceptionTypes() { + List parentExceptionTypes = super.getExceptionTypes(); + List result = new ArrayList( parentExceptionTypes ); + for ( Type exceptionTypeToExclude : exceptionTypesToExclude ) { + for ( Type parentExceptionType : parentExceptionTypes ) { + if ( parentExceptionType.isAssignableTo( exceptionTypeToExclude ) ) { + result.remove( parentExceptionType ); + } + } + } + return result; + } + + public Type getSourceType() { + return sourceType; + } + + @Override + public String getSourceReference() { + return sourceReference; + } + + public String getIteratorReference() { + return getAssignment().getSourceReference(); + } + +} diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java index 725089572..32ed1060c 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/Type.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; - import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; @@ -32,12 +31,13 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; - import org.mapstruct.ap.util.Executables; import org.mapstruct.ap.util.Filters; +import org.mapstruct.ap.util.Nouns; import org.mapstruct.ap.util.TypeUtilsJDK6Fix; /** @@ -75,6 +75,7 @@ public class Type extends ModelElement implements Comparable { private List getters = null; private List setters = null; + private List adders = null; private List alternativeTargetAccessors = null; //CHECKSTYLE:OFF @@ -275,6 +276,70 @@ public class Type extends ModelElement implements Comparable { return getters; } + /** + * Tries to find an addMethod in this type for given collection property in this type. + * + * Matching occurs on: + *
    + *
  • 1. The generic type parameter type of the collection should match the adder method argument
  • + *
  • 2. When there are more candidates, property name is made singular (as good as is possible). This routine + * looks for a matching add method name.
  • + *
  • 3. The singularization rules of Dali are used to make a property name singular. This routine + * looks for a matching add method name.
  • + *
+ * + * @param collectionProperty property type (assumed collection) to find the adder method for + * @param pluralPropertyName the property name (assumed plural) + * + * @return corresponding adder method for getter when present + */ + public ExecutableElement getAdderForType( Type collectionProperty, String pluralPropertyName ) { + + List candidates = new ArrayList(); + if ( collectionProperty.isCollectionType ) { + + // this is a collection, so this can be done always + if ( !collectionProperty.getTypeParameters().isEmpty() ) { + // there's only one type arg to a collection + TypeMirror typeArg = collectionProperty.getTypeParameters().get( 0 ).getTypeMirror(); + // now, look for a method that + // 1) starts with add, + // 2) and has typeArg as one and only arg + List adderList = getAdders(); + for ( ExecutableElement adder : adderList ) { + VariableElement arg = adder.getParameters().get( 0 ); + if ( arg.asType().equals( typeArg ) ) { + candidates.add( adder ); + } + } + } + } + if (candidates.isEmpty()) { + return null; + } + else if (candidates.size() == 1) { + return candidates.get( 0 ); + } + else { + // try to match according human rules + for (ExecutableElement candidate : candidates) { + String adderName = Executables.getElementNameForAdder( candidate ); + if (adderName.equals( Nouns.singularizeHuman( pluralPropertyName ) ) ) { + return candidate; + } + } + // try to match according dali rules + for (ExecutableElement candidate : candidates) { + String adderName = Executables.getElementNameForAdder( candidate ); + if (adderName.equals( Nouns.singularizeDali( pluralPropertyName ) ) ) { + return candidate; + } + } + } + + return null; + } + /** * getSetters * @@ -292,6 +357,24 @@ public class Type extends ModelElement implements Comparable { * Alternative accessors could be a getter for a collection / map. By means of the * {@link Collection#addAll(Collection) } or {@link Map#putAll(Map)} this getter can still be used as * targetAccessor. JAXB XJC tool generates such constructs. This method can be extended when new cases come along. + * getAdders + * + * @return an unmodifiable list of all adders + */ + private List getAdders() { + if ( adders == null ) { + List members = elementUtils.getAllMembers( typeElement ); + adders = Collections.unmodifiableList( Filters.adderMethodsIn( members ) ); + } + return adders; + } + + /** + * Alternative accessors could be a getter for a collection. By means of the + * {@link java.util.Collection#addAll(java.util.Collection) } this getter can still + * be used as targetAccessor. JAXB XJC tool generates such constructs. + * + * This method can be extended when new cases come along. * * @return an unmodifiable list of alternative target accessors. */ 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 0cd211ff2..464e02f6e 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 @@ -190,6 +190,7 @@ public class Mapping { return targetAnnotationValue; } + public Mapping reverse() { Mapping reverse = null; if ( expression != null ) { 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 db9bae67e..ec846c13e 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -35,6 +35,8 @@ import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; +import org.mapstruct.CollectionMappingStrategy; + import org.mapstruct.ap.model.Assignment; import static org.mapstruct.ap.model.Assignment.AssignmentType.DIRECT; import static org.mapstruct.ap.model.Assignment.AssignmentType.TYPE_CONVERTED; @@ -50,6 +52,7 @@ import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.MapperReference; import org.mapstruct.ap.model.MappingMethod; import org.mapstruct.ap.model.PropertyMapping; +import org.mapstruct.ap.model.assignment.AdderWrapper; import org.mapstruct.ap.model.assignment.AssignmentFactory; import org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper; import org.mapstruct.ap.model.assignment.LocalVarWrapper; @@ -81,7 +84,7 @@ import org.mapstruct.ap.util.Strings; */ public class MapperCreationProcessor implements ModelElementProcessor, Mapper> { - private enum TargetAccessorType { GETTER, SETTER }; + private enum TargetAccessorType { GETTER, SETTER, ADDER }; private Elements elementUtils; private Types typeUtils; @@ -108,9 +111,8 @@ public class MapperCreationProcessor implements ModelElementProcessor methods) { - ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element ); List mapperReferences = getReferencedMappers( element ); - List mappingMethods = getMappingMethods( mapperReferences, methods, unmappedTargetPolicy ); + List mappingMethods = getMappingMethods( mapperReferences, methods, element ); mappingMethods.addAll( mappingResolver.getVirtualMethodsToGenerate() ); Mapper mapper = new Mapper.Builder() @@ -151,6 +153,11 @@ public class MapperCreationProcessor implements ModelElementProcessor methods) { DecoratedWithPrism decoratorPrism = DecoratedWithPrism.getInstanceOn( element ); @@ -248,7 +255,7 @@ public class MapperCreationProcessor implements ModelElementProcessor getMappingMethods(List mapperReferences, List methods, - ReportingPolicy unmappedTargetPolicy) { + TypeElement element ) { List mappingMethods = new ArrayList(); for ( SourceMethod method : methods ) { @@ -301,7 +308,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, List methods, SourceMethod method, - ExecutableElement targetAcessor, + ExecutableElement targetAccessor, + String targetPropertyName, Parameter parameter) { - String targetPropertyName = Executables.getPropertyName( targetAcessor ); // check if there's a mapping defined Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName ); @@ -415,7 +422,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences, List methods, - SourceMethod method, ReportingPolicy unmappedTargetPolicy) { + SourceMethod method, TypeElement element) { + + // fetch settings from element to implement + ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element ); + CollectionMappingStrategy cmStrategy = getEffectiveCollectionMappingStrategy( element ); + List propertyMappings = new ArrayList(); Set mappedTargetProperties = new HashSet(); @@ -476,10 +490,44 @@ public class MapperCreationProcessor implements ModelElementProcessor 3 && method.getParameters() + .size() == 1 && method.getReturnType().getKind() == TypeKind.VOID ) { + return true; + } + + return false; + } + private static boolean isPublic(ExecutableElement method) { return method.getModifiers().contains( Modifier.PUBLIC ); } @@ -94,6 +105,35 @@ public class Executables { throw new IllegalArgumentException( "Executable " + getterOrSetterMethod + " is not getter or setter method." ); } + /** + * Returns the 'element name' to which an adder method applies. + * + * If an collection getter / setter are defined by a plural name of the element they apply to, then this + * method gives the supposedly (singular) element name of the collection. + * for example: + * getter = {@code List getChildren()} , then the adder name is supposedly named: {@code addChild(Child v)}, + * element name = 'Child' + * + * getter = {@code List getBikes()} , then the adder name is supposedly named: {@code addBike(Bike v)}, + * element name = 'Bike' + * + * getter = {@code List getGeese()} , then the adder name is supposedly named: {@code addGoose(Goose v)}, + * element name = 'Goose' + * + * @param adderMethod + * + * @return the element name + */ + public static String getElementNameForAdder(ExecutableElement adderMethod) { + if ( isAdderMethod( adderMethod ) ) { + return Introspector.decapitalize( + adderMethod.getSimpleName().toString().substring( 3 ) + ); + } + + throw new IllegalArgumentException( "Executable " + adderMethod + " is not an adder method." ); + } + public static Set getPropertyNames(List propertyAccessors) { Set propertyNames = new HashSet(); diff --git a/processor/src/main/java/org/mapstruct/ap/util/Filters.java b/processor/src/main/java/org/mapstruct/ap/util/Filters.java index 93a49178e..581277413 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/Filters.java +++ b/processor/src/main/java/org/mapstruct/ap/util/Filters.java @@ -58,4 +58,16 @@ public class Filters { } return setterMethods; } + + public static List adderMethodsIn(Iterable elements) { + List adderMethods = new LinkedList(); + + for ( ExecutableElement method : methodsIn( elements ) ) { + if ( Executables.isAdderMethod( method ) ) { + adderMethods.add( method ); + } + } + + return adderMethods; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/util/MapperConfig.java b/processor/src/main/java/org/mapstruct/ap/util/MapperConfig.java index 71d9cacf4..0ead503c0 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/MapperConfig.java +++ b/processor/src/main/java/org/mapstruct/ap/util/MapperConfig.java @@ -27,10 +27,13 @@ import javax.lang.model.element.Element; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.ap.option.ReportingPolicy; import org.mapstruct.ap.prism.MapperConfigPrism; import org.mapstruct.ap.prism.MapperPrism; - +import static org.mapstruct.CollectionMappingStrategy.DEFAULT; +import static org.mapstruct.CollectionMappingStrategy.SETTER_ONLY; +import static org.mapstruct.CollectionMappingStrategy.valueOf; /** * Class decorating the {@link MapperPrism} with the 'default' configuration. * @@ -89,6 +92,25 @@ public class MapperConfig { } } + public CollectionMappingStrategy getCollectionMappingStrategy() { + CollectionMappingStrategy mapperPolicy = valueOf( mapperPrism.collectionMappingStrategy() ); + + if ( !mapperPolicy.equals( DEFAULT ) ) { + // it is not the default mapper configuration, so return the mapper configured value + return mapperPolicy; + } + else if ( mapperConfigPrism != null ) { + // try the config mapper configuration + CollectionMappingStrategy configPolicy = valueOf( mapperConfigPrism.collectionMappingStrategy() ); + if ( !configPolicy.equals( DEFAULT ) ) { + // its not the default configuration, so return the mapper config configured value + return configPolicy; + } + } + // when nothing specified, return SETTER_ONLY (default option) + return SETTER_ONLY; + } + public String componentModel() { if ( !mapperPrism.componentModel().equals( "default" ) ) { return mapperPrism.componentModel(); diff --git a/processor/src/main/java/org/mapstruct/ap/util/Nouns.java b/processor/src/main/java/org/mapstruct/ap/util/Nouns.java new file mode 100644 index 000000000..5fceb9fe6 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/util/Nouns.java @@ -0,0 +1,143 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.util; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class taking care of Noun manipulation + * + * @author Sjaak Derksen + */ +public class Nouns { + + private Nouns() { } + + private static final List SINGULAR_HUMAN_RULES = Arrays.asList( + new ReplaceRule( "(equipment|information|rice|money|species|series|fish|sheep)$", "$1" ), + new ReplaceRule( "(f)eet$", "$1oot" ), + new ReplaceRule( "(t)eeth$", "$1ooth" ), + new ReplaceRule( "(g)eese$", "$1oose" ), + new ReplaceRule( "(s)tadiums$", "$1tadium" ), + new ReplaceRule( "(m)oves$", "$1ove" ), + new ReplaceRule( "(s)exes$", "$1ex" ), + new ReplaceRule( "(c)hildren$", "$1hild" ), + new ReplaceRule( "(m)en$", "$1an" ), + new ReplaceRule( "(p)eople$", "$1erson" ), + new ReplaceRule( "(quiz)zes$", "$1" ), + new ReplaceRule( "(matr)ices$", "$1ix" ), + new ReplaceRule( "(vert|ind)ices$", "$1ex" ), + new ReplaceRule( "^(ox)en", "$1" ), + new ReplaceRule( "(alias|status)$", "$1" ), // already singular, but ends in 's' + new ReplaceRule( "(alias|status)es$", "$1" ), + new ReplaceRule( "(octop|vir)us$", "$1us" ), // already singular, but ends in 's' + new ReplaceRule( "(octop|vir)i$", "$1us" ), + new ReplaceRule( "(cris|ax|test)es$", "$1is" ), + new ReplaceRule( "(cris|ax|test)is$", "$1is" ), // already singular, but ends in 's' + new ReplaceRule( "(shoe)s$", "$1" ), + new ReplaceRule( "(o)es$", "$1" ), + new ReplaceRule( "(bus)es$", "$1" ), + new ReplaceRule( "([m|l])ice$", "$1ouse" ), + new ReplaceRule( "(x|ch|ss|sh)es$", "$1" ), + new ReplaceRule( "(m)ovies$", "$1ovie" ), + new ReplaceRule( "(s)eries$", "$1eries" ), + new ReplaceRule( "([^aeiouy]|qu)ies$", "$1y" ), + new ReplaceRule( "([lr])ves$", "$1f" ), + new ReplaceRule( "(tive)s$", "$1" ), + new ReplaceRule( "(hive)s$", "$1" ), + new ReplaceRule( "([^f])ves$", "$1fe" ), + new ReplaceRule( "(^analy)sis$", "$1sis" ), // already singular, but ends in 's' + new ReplaceRule( "(^analy)ses$", "$1sis" ), + new ReplaceRule( "((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis" ), + new ReplaceRule( "([ti])a$", "$1um" ), + new ReplaceRule( "(n)ews$", "$1ews" ), + new ReplaceRule( "(s|si|u)s$", "$1s" ), // '-us' and '-ss' are already singular + new ReplaceRule( "s$", "" ) + ); + + private static final List SINGULAR_DALI_RULES = Arrays.asList( + new ReplaceRule( "(us|ss)$", "$1" ), + new ReplaceRule( "(ch|s)es$", "$1" ), + new ReplaceRule( "([^aeiouy])ies$", "$1y" ), + new ReplaceRule( "s$", "" ) + ); + + /** + * Converts given in into a singular form as much as possible according human form. This will always be a best + * attempt. The rules are language context dependent and + * + * @param in String to singularize + * @return singularize form of in + */ + public static String singularizeHuman( String in ) { + for ( ReplaceRule replaceRule : SINGULAR_HUMAN_RULES ) { + String match = replaceRule.apply( in ); + if ( match != null ) { + return match; + } + } + return in; + } + + /** + * Converts given in into a singular form according dali + * @see rules + * + * These rules are assumed to be incomplete and give wrong conversions from plural to singular that should + * be taken into account as well. + * + * @param in String to singularize + * @return singularize form of in + */ + public static String singularizeDali( String in ) { + for ( ReplaceRule replaceRule : SINGULAR_DALI_RULES ) { + String match = replaceRule.apply( in ); + if ( match != null ) { + return match; + } + } + return in; + } + + private static final class ReplaceRule { + + private final String regexp; + private final String replacement; + private final Pattern pattern; + + private ReplaceRule( String regexp, String replacement ) { + this.regexp = regexp; + this.replacement = replacement; + this.pattern = Pattern.compile( this.regexp, Pattern.CASE_INSENSITIVE ); + } + + private String apply( String input ) { + String result = null; + Matcher matcher = this.pattern.matcher( input ); + if ( matcher.find() ) { + result = matcher.replaceAll( this.replacement ); + } + return result; + } + + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/util/Strings.java b/processor/src/main/java/org/mapstruct/ap/util/Strings.java index 8ddacc5d7..2ed124bf3 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/Strings.java +++ b/processor/src/main/java/org/mapstruct/ap/util/Strings.java @@ -33,70 +33,70 @@ import static org.mapstruct.ap.util.Collections.asSet; public class Strings { private static final Set KEYWORDS = asSet( - "abstract", - "continue", - "for", - "new", - "switch", - "assert", - "default", - "goto", - "package", - "synchronized", - "boolean", - "do", - "if", - "private", - "this", - "break", - "double", - "implements", - "protected", - "throw", - "byte", - "else", - "import", - "public", - "throws", - "case", - "enum", - "instanceof", - "return", - "transient", - "catch", - "extends", - "int", - "short", - "try", - "char", - "final", - "interface", - "static", - "void", - "class", - "finally", - "long", - "strictfp", - "volatile", - "const", - "float", - "native", - "super", - "while" + "abstract", + "continue", + "for", + "new", + "switch", + "assert", + "default", + "goto", + "package", + "synchronized", + "boolean", + "do", + "if", + "private", + "this", + "break", + "double", + "implements", + "protected", + "throw", + "byte", + "else", + "import", + "public", + "throws", + "case", + "enum", + "instanceof", + "return", + "transient", + "catch", + "extends", + "int", + "short", + "try", + "char", + "final", + "interface", + "static", + "void", + "class", + "finally", + "long", + "strictfp", + "volatile", + "const", + "float", + "native", + "super", + "while" ); private Strings() { } - public static String capitalize(String string) { + public static String capitalize( String string ) { return string == null ? null : string.substring( 0, 1 ).toUpperCase() + string.substring( 1 ); } - public static String decapitalize(String string) { + public static String decapitalize( String string ) { return string == null ? null : string.substring( 0, 1 ).toLowerCase() + string.substring( 1 ); } - public static String join(Iterable iterable, String separator) { + public static String join( Iterable iterable, String separator ) { StringBuilder sb = new StringBuilder(); boolean isFirst = true; @@ -114,11 +114,11 @@ public class Strings { return sb.toString(); } - public static boolean isEmpty(String string) { + public static boolean isEmpty( String string ) { return string == null || string.isEmpty(); } - public static String getSaveVariableName(String name, String... existingVariableNames) { + public static String getSaveVariableName( String name, String... existingVariableNames ) { return getSaveVariableName( name, Arrays.asList( existingVariableNames ) ); } @@ -130,9 +130,9 @@ public class Strings { * @param existingVariableNames the names of other variables existing in the same scope * * @return a variable name based on the given original name, not conflicting with any of the given other names or - * any Java keyword; starting with a lower-case letter + * any Java keyword; starting with a lower-case letter */ - public static String getSaveVariableName(String name, Collection existingVariableNames) { + public static String getSaveVariableName( String name, Collection existingVariableNames ) { name = decapitalize( name ); Set conflictingNames = new HashSet( KEYWORDS ); @@ -144,4 +144,5 @@ public class Strings { return name; } + } diff --git a/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl b/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl new file mode 100644 index 000000000..29123f0c5 --- /dev/null +++ b/processor/src/main/resources/org.mapstruct.ap.model.assignment.AdderWrapper.ftl @@ -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. + +--> +<#if (exceptionTypes?size == 0) > + for ( <@includeModel object=sourceType/> ${iteratorReference} : ${sourceReference} ) { + ${ext.targetBeanName}.${ext.targetAccessorName}( <@includeModel object=assignment + targetBeanName=ext.targetBeanName + raw=ext.raw + existingInstanceMapping=ext.existingInstanceMapping + targetAccessorName=ext.targetAccessorName + targetType=ext.targetType/> ); + } +<#else> + try { + for ( <@includeModel object=sourceType/> ${iteratorReference} : ${sourceReference} ) { + ${ext.targetBeanName}.${ext.targetAccessorName}( <@includeModel object=assignment + targetBeanName=ext.targetBeanName + raw=ext.raw + existingInstanceMapping=ext.existingInstanceMapping + targetAccessorName=ext.targetAccessorName + targetType=ext.targetType/> ); + } + } + <#list exceptionTypes as exceptionType> + catch ( <@includeModel object=exceptionType/> e ) { + throw new RuntimeException( e ); + } + + \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java new file mode 100644 index 000000000..8abaf994d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/AdderTest.java @@ -0,0 +1,221 @@ +/** + * 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.collection.adder; + +import org.mapstruct.ap.test.collection.adder.target.AdderUsageObserver; +import org.mapstruct.ap.test.collection.adder.source.Source; +import org.mapstruct.ap.test.collection.adder.source.SourceTeeth; +import org.mapstruct.ap.test.collection.adder.target.TargetOnlyGetter; +import org.mapstruct.ap.test.collection.adder.target.TargetHuman; +import org.mapstruct.ap.test.collection.adder.target.TargetDali; +import org.mapstruct.ap.test.collection.adder.target.Target; +import org.mapstruct.ap.test.collection.adder.target.TargetViaTargetType; +import org.mapstruct.ap.test.collection.adder.target.TargetWithoutSetter; +import java.util.ArrayList; +import java.util.Arrays; +import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.test.collection.adder.target.IndoorPet; +import org.mapstruct.ap.test.collection.adder.target.OutdoorPet; +import org.mapstruct.ap.test.collection.adder.target.Pet; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * + * @author Sjaak Derksen + */ +@WithClasses( { + Source.class, + SourceTeeth.class, + Target.class, + TargetDali.class, + TargetHuman.class, + TargetOnlyGetter.class, + TargetViaTargetType.class, + TargetWithoutSetter.class, + SourceTargetMapper.class, + SourceTargetMapperStrategyDefault.class, + SourceTargetMapperStrategySetterPreferred.class, + PetMapper.class, + TeethMapper.class, + AdderUsageObserver.class, + Pet.class, + IndoorPet.class, + OutdoorPet.class, + DogException.class, + CatException.class } ) +@RunWith( AnnotationProcessorTestRunner.class ) +public class AdderTest { + + @Test + public void testAdd() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + Target target = SourceTargetMapper.INSTANCE.toTarget( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( 2L ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test( expected = DogException.class ) + public void testAddWithExceptionInThrowsClause() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "dog" ) ); + + SourceTargetMapper.INSTANCE.toTarget( source ); + } + + @Test( expected = RuntimeException.class ) + public void testAddWithExceptionNotInThrowsClause() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "cat" ) ); + + SourceTargetMapper.INSTANCE.toTarget( source ); + } + + @Test + public void testAddwithExistingTarget() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + Target target = new Target(); + target.setPets( new ArrayList( Arrays.asList( 1L ) ) ); + + SourceTargetMapper.INSTANCE.toExistingTarget( source, target ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 2 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( 1L ); + assertThat( target.getPets().get( 1 ) ).isEqualTo( 2L ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test + public void testShouldUseDefaultStrategy() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + Target target = SourceTargetMapperStrategyDefault.INSTANCE.shouldFallBackToAdder( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( 2L ); + assertFalse( AdderUsageObserver.isUsed() ); + } + + @Test + public void testShouldPreferSetterStrategyButThereIsNone() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + TargetWithoutSetter target = SourceTargetMapperStrategySetterPreferred.INSTANCE.toTargetDontUseAdder( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( 2L ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test + public void testShouldPreferHumanSingular() { + + AdderUsageObserver.setUsed( false ); + + SourceTeeth source = new SourceTeeth(); + source.setTeeth( Arrays.asList( "moler" ) ); + + TargetHuman target = SourceTargetMapper.INSTANCE.toTargetHuman( source ); + assertThat( target ).isNotNull(); + assertThat( target.getTeeth().size() ).isEqualTo( 1 ); + assertThat( target.getTeeth().get( 0 ) ).isEqualTo( 3 ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test + public void testshouldFallBackToDaliSingularInAbsenseOfHumanSingular() { + AdderUsageObserver.setUsed( false ); + + SourceTeeth source = new SourceTeeth(); + source.setTeeth( Arrays.asList( "moler" ) ); + + TargetDali target = SourceTargetMapper.INSTANCE.toTargetDali( source ); + assertThat( target ).isNotNull(); + assertThat( target.getTeeth().size() ).isEqualTo( 1 ); + assertThat( target.getTeeth().get( 0 ) ).isEqualTo( 3 ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test + public void testAddReverse() throws DogException { + AdderUsageObserver.setUsed( false ); + + Target source = new Target(); + source.setPets( Arrays.asList( 3L ) ); + + Source target = SourceTargetMapper.INSTANCE.toSource( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( "cat" ); + } + + @Test + public void testAddOnlyGetter() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + TargetOnlyGetter target = SourceTargetMapper.INSTANCE.toTargetOnlyGetter( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isEqualTo( 2L ); + assertTrue( AdderUsageObserver.isUsed() ); + } + + @Test + public void testAddViaTargetType() throws DogException { + AdderUsageObserver.setUsed( false ); + + Source source = new Source(); + source.setPets( Arrays.asList( "mouse" ) ); + + TargetViaTargetType target = SourceTargetMapper.INSTANCE.toTargetViaTargetType( source ); + assertThat( target ).isNotNull(); + assertThat( target.getPets().size() ).isEqualTo( 1 ); + assertThat( target.getPets().get( 0 ) ).isNotNull(); + assertThat( target.getPets().get( 0 ).getValue() ).isEqualTo( 2L ); + assertTrue( AdderUsageObserver.isUsed() ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/CatException.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/CatException.java new file mode 100644 index 000000000..fb84834ba --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/CatException.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.collection.adder; + +/** + * + * @author Sjaak Derksen + */ +public class CatException extends Exception { + + public CatException() { + } + + public CatException( String msg ) { + super( msg ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/DogException.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/DogException.java new file mode 100644 index 000000000..22c068cf6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/DogException.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.collection.adder; + +/** + * + * @author Sjaak Derksen + */ +public class DogException extends Exception { + + public DogException() { + } + + public DogException( String msg ) { + super( msg ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/PetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/PetMapper.java new file mode 100644 index 000000000..bcb72f6ca --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/PetMapper.java @@ -0,0 +1,99 @@ +/** + * 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.collection.adder; + +import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.mapstruct.TargetType; +import org.mapstruct.ap.test.collection.adder.target.IndoorPet; +import org.mapstruct.ap.test.collection.adder.target.OutdoorPet; +import org.mapstruct.ap.test.collection.adder.target.Pet; + +/** + * + * @author Sjaak Derksen + */ +public class PetMapper { + + private static final Map PETS_TO_TARGET = ImmutableMap.builder() + .put( "rabbit", 1L ) + .put( "mouse", 2L ).build(); + + private static final Map PETS_TO_SOURCE = ImmutableMap.builder() + .put( 1L, "rabbit" ) + .put( 2L, "mouse" ) + .put( 3L, "cat" ) + .put( 4L, "dog" ).build(); + + + /** + * method to be used when using an adder + * + * @param pet + * @return + * @throws CatException + * @throws DogException + */ + public Long toPet( String pet ) throws CatException, DogException { + if ( "cat".equals( pet ) ) { + throw new CatException(); + } + else if ( "dog".equals( pet ) ) { + throw new DogException(); + } + return PETS_TO_TARGET.get( pet ); + } + + /** + * Method to be used when not using an adder + * + * @param pets + * @return + * @throws CatException + * @throws DogException + */ + public List toPets( List pets ) throws CatException, DogException { + List result = new ArrayList(); + for (String pet : pets) { + result.add( toPet( pet) ); + } + return result; + } + + @SuppressWarnings( "unchecked" ) + public T toPet(String pet, @TargetType Class clazz) throws CatException, DogException { + if ( clazz == IndoorPet.class ) { + return (T) new IndoorPet( toPet( pet ) ); + } + if ( clazz == OutdoorPet.class ) { + return (T) new OutdoorPet( toPet( pet ) ); + } + return null; + } + + public List toSourcePets( List pets ) throws CatException, DogException { + List result = new ArrayList(); + for (Long pet : pets) { + result.add( PETS_TO_SOURCE.get( pet ) ); + } + return result; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapper.java new file mode 100644 index 000000000..d55a2bdba --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapper.java @@ -0,0 +1,55 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.collection.adder; + +import org.mapstruct.ap.test.collection.adder.source.Source; +import org.mapstruct.ap.test.collection.adder.source.SourceTeeth; +import org.mapstruct.ap.test.collection.adder.target.TargetOnlyGetter; +import org.mapstruct.ap.test.collection.adder.target.TargetHuman; +import org.mapstruct.ap.test.collection.adder.target.TargetDali; +import org.mapstruct.ap.test.collection.adder.target.Target; +import org.mapstruct.ap.test.collection.adder.target.TargetViaTargetType; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, + uses = { PetMapper.class, TeethMapper.class } ) +public interface SourceTargetMapper { + + SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); + + Target toTarget( Source source ) throws DogException; + Source toSource( Target source ); + + void toExistingTarget( Source source, @MappingTarget Target target ); + + TargetDali toTargetDali( SourceTeeth source ); + + TargetHuman toTargetHuman( SourceTeeth source ); + + TargetOnlyGetter toTargetOnlyGetter( Source source ) throws DogException; + + TargetViaTargetType toTargetViaTargetType( Source source ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategyDefault.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategyDefault.java new file mode 100644 index 000000000..61005590b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategyDefault.java @@ -0,0 +1,37 @@ +/** + * 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.collection.adder; + +import org.mapstruct.ap.test.collection.adder.source.Source; +import org.mapstruct.ap.test.collection.adder.target.Target; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = { PetMapper.class } ) +public interface SourceTargetMapperStrategyDefault { + + SourceTargetMapperStrategyDefault INSTANCE = Mappers.getMapper( SourceTargetMapperStrategyDefault.class ); + + Target shouldFallBackToAdder( Source source ) throws DogException; + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategySetterPreferred.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategySetterPreferred.java new file mode 100644 index 000000000..e70fb6231 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/SourceTargetMapperStrategySetterPreferred.java @@ -0,0 +1,41 @@ +/** + * 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.collection.adder; + +import org.mapstruct.ap.test.collection.adder.source.Source; +import org.mapstruct.ap.test.collection.adder.target.TargetWithoutSetter; +import org.mapstruct.CollectionMappingStrategy; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( collectionMappingStrategy = CollectionMappingStrategy.SETTER_PREFERRED, + uses = { PetMapper.class } +) +public interface SourceTargetMapperStrategySetterPreferred { + + SourceTargetMapperStrategySetterPreferred INSTANCE = + Mappers.getMapper( SourceTargetMapperStrategySetterPreferred.class ); + + TargetWithoutSetter toTargetDontUseAdder( Source source ) throws DogException; + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/TeethMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/TeethMapper.java new file mode 100644 index 000000000..5922a8ae0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/TeethMapper.java @@ -0,0 +1,38 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.collection.adder; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public class TeethMapper { + + private static final Map TEETH = ImmutableMap.builder() + .put( "incisor", 1 ) + .put( "canine", 2 ) + .put( "moler", 3 ).build(); + + public Integer toTooth( String tooth ) { + return TEETH.get( tooth ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/Source.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/Source.java new file mode 100644 index 000000000..2758c5aff --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/Source.java @@ -0,0 +1,38 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.collection.adder.source; + +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class Source { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets( List pets ) { + this.pets = pets; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceTeeth.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceTeeth.java new file mode 100644 index 000000000..b84d2a0ca --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/source/SourceTeeth.java @@ -0,0 +1,38 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.collection.adder.source; + +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class SourceTeeth { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth( List teeth ) { + this.teeth = teeth; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/AdderUsageObserver.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/AdderUsageObserver.java new file mode 100644 index 000000000..a0cf61c28 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/AdderUsageObserver.java @@ -0,0 +1,39 @@ +/** + * 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.collection.adder.target; + +/** + * + * @author Sjaak Derksen + */ +public class AdderUsageObserver { + + private AdderUsageObserver() { } + + private static boolean used = false; + + public static boolean isUsed() { + return used; + } + + public static void setUsed( boolean used ) { + AdderUsageObserver.used = used; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/IndoorPet.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/IndoorPet.java new file mode 100644 index 000000000..cde9b2ad7 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/IndoorPet.java @@ -0,0 +1,43 @@ +/** + * 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.collection.adder.target; + +/** + * + * @author Sjaak Derksen + */ +public class IndoorPet extends Pet { + + private Long value; + + public IndoorPet( Long value ) { + this.value = value; + } + + public Long getValue() { + return value; + } + + public void setValue( Long value ) { + this.value = value; + } + + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/OutdoorPet.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/OutdoorPet.java new file mode 100644 index 000000000..4d15b35aa --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/OutdoorPet.java @@ -0,0 +1,43 @@ +/** + * 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.collection.adder.target; + +/** + * + * @author Sjaak Derksen + */ +public class OutdoorPet extends Pet { + + private Long value; + + public OutdoorPet( Long value ) { + this.value = value; + } + + public Long getValue() { + return value; + } + + public void setValue( Long value ) { + this.value = value; + } + + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Pet.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Pet.java new file mode 100644 index 000000000..91def42d9 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Pet.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.collection.adder.target; + +/** + * + * @author Sjaak Derksen + */ +public class Pet { + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Target.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Target.java new file mode 100644 index 000000000..e9c55541b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/Target.java @@ -0,0 +1,59 @@ +/** + * 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.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class Target { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets( List pets ) { + this.pets = pets; + } + + public void addCat( Long cat ) { + // dummy method to test selection mechanims + } + + public void addDog( Long cat ) { + // dummy method to test selection mechanims + } + + public void addPets( Long cat ) { + // dummy method to test selection mechanims + } + + public void addPet( Long pet ) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList(); + } + pets.add( pet ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetDali.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetDali.java new file mode 100644 index 000000000..79b3eec67 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetDali.java @@ -0,0 +1,48 @@ +/** + * 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.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetDali { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth( List teeth ) { + this.teeth = teeth; + } + + public void addTeeth( Integer tooth ) { + AdderUsageObserver.setUsed( true ); + if ( teeth == null ) { + teeth = new ArrayList(); + } + teeth.add( tooth ); + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetHuman.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetHuman.java new file mode 100644 index 000000000..d2f568363 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetHuman.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.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetHuman { + + private List teeth; + + public List getTeeth() { + return teeth; + } + + public void setTeeth( List teeth ) { + this.teeth = teeth; + } + + public void addTooth( Integer pet ) { + AdderUsageObserver.setUsed( true ); + if ( teeth == null ) { + teeth = new ArrayList(); + } + teeth.add( pet ); + } + + public void addTeeth( Integer tooth ) { + if ( teeth == null ) { + teeth = new ArrayList(); + } + teeth.add( tooth ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetOnlyGetter.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetOnlyGetter.java new file mode 100644 index 000000000..47e113433 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetOnlyGetter.java @@ -0,0 +1,55 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetOnlyGetter { + + private List pets; + + public List getPets() { + return pets; + } + + public void addCat( Long cat ) { + // dummy method to test selection mechanims + } + + public void addDog( Long cat ) { + // dummy method to test selection mechanims + } + + public void addPets( Long cat ) { + // dummy method to test selection mechanims + } + + public void addPet( Long pet ) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList(); + } + pets.add( pet ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetViaTargetType.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetViaTargetType.java new file mode 100644 index 000000000..0a216221f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetViaTargetType.java @@ -0,0 +1,47 @@ +/** + * 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.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetViaTargetType { + + private List pets; + + public List getPets() { + return pets; + } + + public void setPets( List pets ) { + this.pets = pets; + } + + public void addPet( IndoorPet pet ) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList(); + } + pets.add( pet ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetWithoutSetter.java b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetWithoutSetter.java new file mode 100644 index 000000000..2076cc33f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/adder/target/TargetWithoutSetter.java @@ -0,0 +1,43 @@ +/** + * 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.collection.adder.target; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public class TargetWithoutSetter { + + private List pets; + + public List getPets() { + return pets; + } + + public void addPet( Long pet ) { + AdderUsageObserver.setUsed( true ); + if ( pets == null ) { + pets = new ArrayList(); + } + pets.add( pet ); + } +}