mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#207 adder method support for target collections and unit test
This commit is contained in:
parent
6d682c5118
commit
acfca6235d
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -76,4 +76,5 @@ public @interface Mapping {
|
||||
* @return A constant {@code String} expression specifying the value for the designated target prperty
|
||||
*/
|
||||
String expression() default "";
|
||||
|
||||
}
|
||||
|
@ -74,4 +74,5 @@ public @interface Mapping {
|
||||
* @return A constant {@code String} expression specifying the value for the designated target prperty
|
||||
*/
|
||||
String expression() default "";
|
||||
|
||||
}
|
||||
|
@ -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<Type> exceptionTypesToExclude;
|
||||
private final String sourceReference;
|
||||
private final Type sourceType;
|
||||
|
||||
public AdderWrapper(
|
||||
Assignment decoratedAssignment,
|
||||
List<Type> exceptionTypesToExclude,
|
||||
String sourceReference,
|
||||
Type sourceType) {
|
||||
super( decoratedAssignment );
|
||||
this.exceptionTypesToExclude = exceptionTypesToExclude;
|
||||
this.sourceReference = sourceReference;
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Type> getExceptionTypes() {
|
||||
List<Type> parentExceptionTypes = super.getExceptionTypes();
|
||||
List<Type> result = new ArrayList<Type>( 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();
|
||||
}
|
||||
|
||||
}
|
@ -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<Type> {
|
||||
|
||||
private List<ExecutableElement> getters = null;
|
||||
private List<ExecutableElement> setters = null;
|
||||
private List<ExecutableElement> adders = null;
|
||||
private List<ExecutableElement> alternativeTargetAccessors = null;
|
||||
|
||||
//CHECKSTYLE:OFF
|
||||
@ -275,6 +276,70 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
return getters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find an addMethod in this type for given collection property in this type.
|
||||
*
|
||||
* Matching occurs on:
|
||||
* <ul>
|
||||
* <li>1. The generic type parameter type of the collection should match the adder method argument</li>
|
||||
* <li>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.</li>
|
||||
* <li>3. The singularization rules of Dali are used to make a property name singular. This routine
|
||||
* looks for a matching add method name.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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<ExecutableElement> candidates = new ArrayList<ExecutableElement>();
|
||||
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<ExecutableElement> 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<Type> {
|
||||
* 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<ExecutableElement> getAdders() {
|
||||
if ( adders == null ) {
|
||||
List<? extends Element> 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.
|
||||
*/
|
||||
|
@ -190,6 +190,7 @@ public class Mapping {
|
||||
return targetAnnotationValue;
|
||||
}
|
||||
|
||||
|
||||
public Mapping reverse() {
|
||||
Mapping reverse = null;
|
||||
if ( expression != null ) {
|
||||
|
@ -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<List<SourceMethod>, 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<List<Sourc
|
||||
}
|
||||
|
||||
private Mapper getMapper(TypeElement element, List<SourceMethod> methods) {
|
||||
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
|
||||
List<MapperReference> mapperReferences = getReferencedMappers( element );
|
||||
List<MappingMethod> mappingMethods = getMappingMethods( mapperReferences, methods, unmappedTargetPolicy );
|
||||
List<MappingMethod> mappingMethods = getMappingMethods( mapperReferences, methods, element );
|
||||
mappingMethods.addAll( mappingResolver.getVirtualMethodsToGenerate() );
|
||||
|
||||
Mapper mapper = new Mapper.Builder()
|
||||
@ -151,6 +153,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
}
|
||||
|
||||
private CollectionMappingStrategy getEffectiveCollectionMappingStrategy(TypeElement element) {
|
||||
MapperConfig mapperSettings = MapperConfig.getInstanceOn( element );
|
||||
return mapperSettings.getCollectionMappingStrategy();
|
||||
}
|
||||
|
||||
private Decorator getDecorator(TypeElement element, List<SourceMethod> methods) {
|
||||
DecoratedWithPrism decoratorPrism = DecoratedWithPrism.getInstanceOn( element );
|
||||
|
||||
@ -248,7 +255,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
|
||||
private List<MappingMethod> getMappingMethods(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||
ReportingPolicy unmappedTargetPolicy) {
|
||||
TypeElement element ) {
|
||||
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
||||
|
||||
for ( SourceMethod method : methods ) {
|
||||
@ -301,7 +308,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
mapperReferences,
|
||||
methods,
|
||||
method,
|
||||
unmappedTargetPolicy
|
||||
element
|
||||
);
|
||||
if ( beanMappingMethod != null ) {
|
||||
hasFactoryMethod = beanMappingMethod.getFactoryMethod() != null;
|
||||
@ -386,9 +393,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
private PropertyMapping getPropertyMapping(List<MapperReference> mapperReferences,
|
||||
List<SourceMethod> 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<List<Sourc
|
||||
methods,
|
||||
method,
|
||||
sourceConstant,
|
||||
targetAcessor,
|
||||
targetAccessor,
|
||||
dateFormat
|
||||
);
|
||||
}
|
||||
@ -435,7 +442,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
method,
|
||||
parameter,
|
||||
sourceAccessor,
|
||||
targetAcessor,
|
||||
targetAccessor,
|
||||
targetPropertyName,
|
||||
dateFormat
|
||||
);
|
||||
}
|
||||
@ -448,7 +456,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
method,
|
||||
parameter,
|
||||
sourceAccessor,
|
||||
targetAcessor,
|
||||
targetAccessor,
|
||||
targetPropertyName,
|
||||
dateFormat
|
||||
);
|
||||
}
|
||||
@ -457,7 +466,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
|
||||
private BeanMappingMethod getBeanMappingMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||
SourceMethod method, ReportingPolicy unmappedTargetPolicy) {
|
||||
SourceMethod method, TypeElement element) {
|
||||
|
||||
// fetch settings from element to implement
|
||||
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
|
||||
CollectionMappingStrategy cmStrategy = getEffectiveCollectionMappingStrategy( element );
|
||||
|
||||
|
||||
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||
Set<String> mappedTargetProperties = new HashSet<String>();
|
||||
@ -476,10 +490,44 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
|
||||
Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName );
|
||||
|
||||
// A target access is in general a setter method on the target object. However, in case of collections,
|
||||
// the current target accessor can also be a getter method.
|
||||
//
|
||||
// The following if block, checks if the target accessor should be overruled by an add method.
|
||||
if ( cmStrategy.equals( CollectionMappingStrategy.SETTER_PREFERRED ) ||
|
||||
cmStrategy.equals( CollectionMappingStrategy.ADDER_PREFERRED ) ) {
|
||||
|
||||
// first check if there's a setter method.
|
||||
ExecutableElement adderAccessor = null;
|
||||
if ( Executables.isSetterMethod( targetAccessor ) ) {
|
||||
Type targetType = typeFactory.getSingleParameter( targetAccessor ).getType();
|
||||
// ok, the current accessor is a setter. So now the strategy determines what to use
|
||||
if ( cmStrategy.equals( CollectionMappingStrategy.ADDER_PREFERRED ) ) {
|
||||
adderAccessor = method.getResultType().getAdderForType( targetType, targetPropertyName );
|
||||
}
|
||||
}
|
||||
else if ( Executables.isGetterMethod( targetAccessor ) ) {
|
||||
// the current accessor is a getter (no setter available). But still, an add method is according
|
||||
// to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
|
||||
Type targetType = typeFactory.getReturnType( targetAccessor );
|
||||
adderAccessor = method.getResultType().getAdderForType( targetType, targetPropertyName );
|
||||
}
|
||||
if ( adderAccessor != null ) {
|
||||
// an adder has been found (according strategy) so overrule current choice.
|
||||
targetAccessor = adderAccessor;
|
||||
}
|
||||
}
|
||||
|
||||
PropertyMapping propertyMapping = null;
|
||||
if ( mapping != null && mapping.getSourceParameterName() != null ) {
|
||||
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
|
||||
propertyMapping = getPropertyMapping( mapperReferences, methods, method, targetAccessor, parameter );
|
||||
propertyMapping = getPropertyMapping(
|
||||
mapperReferences,
|
||||
methods,
|
||||
method,
|
||||
targetAccessor,
|
||||
targetPropertyName,
|
||||
parameter );
|
||||
}
|
||||
|
||||
if ( propertyMapping == null ) {
|
||||
@ -489,6 +537,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
methods,
|
||||
method,
|
||||
targetAccessor,
|
||||
targetPropertyName,
|
||||
sourceParameter
|
||||
);
|
||||
if ( propertyMapping != null && newPropertyMapping != null ) {
|
||||
@ -657,24 +706,36 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
SourceMethod method,
|
||||
Parameter parameter,
|
||||
ExecutableElement sourceAccessor,
|
||||
ExecutableElement targetAcessor,
|
||||
ExecutableElement targetAccessor,
|
||||
String targetPropertyName,
|
||||
String dateFormat) {
|
||||
|
||||
TargetAccessorType targetAccessorType = TargetAccessorType.SETTER;
|
||||
Type sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||
Type sourceType;
|
||||
Type targetType;
|
||||
TargetAccessorType targetAccessorType;
|
||||
String sourceReference = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
||||
if ( Executables.isSetterMethod( targetAcessor ) ) {
|
||||
targetType = typeFactory.getSingleParameter( targetAcessor ).getType();
|
||||
String iteratorReference = null;
|
||||
if ( Executables.isSetterMethod( targetAccessor ) ) {
|
||||
sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||
targetType = typeFactory.getSingleParameter( targetAccessor ).getType();
|
||||
targetAccessorType = TargetAccessorType.SETTER;
|
||||
}
|
||||
else { // must be getter
|
||||
targetType = typeFactory.getReturnType( targetAcessor );
|
||||
else if ( Executables.isAdderMethod( targetAccessor ) ) {
|
||||
sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||
if ( sourceType.isCollectionType() && !sourceType.getTypeParameters().isEmpty() ) {
|
||||
sourceType = sourceType.getTypeParameters().get( 0 );
|
||||
iteratorReference = Executables.getElementNameForAdder( targetAccessor );
|
||||
}
|
||||
targetType = typeFactory.getSingleParameter( targetAccessor ).getType();
|
||||
targetAccessorType = TargetAccessorType.ADDER;
|
||||
}
|
||||
else {
|
||||
sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||
targetType = typeFactory.getReturnType( targetAccessor );
|
||||
targetAccessorType = TargetAccessorType.GETTER;
|
||||
}
|
||||
|
||||
String targetPropertyName = Executables.getPropertyName( targetAcessor );
|
||||
|
||||
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
||||
String sourcePropertyName = Executables.getPropertyName( sourceAccessor );
|
||||
String mappedElement = "property '" + sourcePropertyName + "'";
|
||||
|
||||
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||
method,
|
||||
@ -685,7 +746,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
targetType,
|
||||
targetPropertyName,
|
||||
dateFormat,
|
||||
sourceReference
|
||||
iteratorReference != null ? iteratorReference : sourceReference
|
||||
);
|
||||
|
||||
if ( assignment != null ) {
|
||||
@ -703,19 +764,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
||||
|
||||
// wrap the setter in the collection / map initializers
|
||||
switch ( targetAccessorType ) {
|
||||
|
||||
case GETTER:
|
||||
// target accessor is getter, so decorate assignment as getter
|
||||
assignment = new GetterCollectionOrMapWrapper( assignment,
|
||||
targetAcessor.getSimpleName().toString() );
|
||||
break;
|
||||
|
||||
default: // setter
|
||||
|
||||
assignment = new SetterCollectionOrMapWrapper( assignment,
|
||||
targetAcessor.getSimpleName().toString() );
|
||||
break;
|
||||
if ( targetAccessorType == TargetAccessorType.SETTER ) {
|
||||
// target accessor is setter, so decorate assignment as setter
|
||||
assignment = new SetterCollectionOrMapWrapper( assignment,
|
||||
targetAccessor.getSimpleName().toString() );
|
||||
}
|
||||
else {
|
||||
// target accessor is getter, so decorate assignment as getter
|
||||
assignment = new GetterCollectionOrMapWrapper( assignment,
|
||||
targetAccessor.getSimpleName().toString() );
|
||||
}
|
||||
|
||||
// For collections and maps include a null check, when the assignment type is DIRECT.
|
||||
@ -728,11 +785,17 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
else {
|
||||
|
||||
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
||||
if ( !sourceType.isPrimitive() && ( assignment.getType() == TYPE_CONVERTED ) ) {
|
||||
if ( targetAccessorType == TargetAccessorType.SETTER ) {
|
||||
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
||||
if ( !sourceType.isPrimitive() && ( assignment.getType() == TYPE_CONVERTED ) ) {
|
||||
// for primitive types null check is not possible at all, but a conversion needs
|
||||
// a null check.
|
||||
assignment = new NullCheckWrapper( assignment );
|
||||
// a null check.
|
||||
assignment = new NullCheckWrapper( assignment );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// adder, so wrap as adder
|
||||
assignment = new AdderWrapper( assignment, method.getThrownTypes(), sourceReference, sourceType );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -742,16 +805,16 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
String.format(
|
||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||
sourceType,
|
||||
Executables.getPropertyName( sourceAccessor ),
|
||||
sourcePropertyName,
|
||||
targetType,
|
||||
Executables.getPropertyName( targetAcessor )
|
||||
targetPropertyName
|
||||
),
|
||||
method.getExecutable()
|
||||
);
|
||||
}
|
||||
return new PropertyMapping(
|
||||
parameter.getName(),
|
||||
targetAcessor.getSimpleName().toString(),
|
||||
targetAccessor.getSimpleName().toString(),
|
||||
targetType,
|
||||
assignment
|
||||
);
|
||||
|
@ -70,6 +70,17 @@ public class Executables {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAdderMethod(ExecutableElement method) {
|
||||
String name = method.getSimpleName().toString();
|
||||
|
||||
if ( isPublic( method ) && name.startsWith( "add" ) && name.length() > 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<Child> getChildren()} , then the adder name is supposedly named: {@code addChild(Child v)},
|
||||
* element name = 'Child'
|
||||
*
|
||||
* getter = {@code List<Bike> getBikes()} , then the adder name is supposedly named: {@code addBike(Bike v)},
|
||||
* element name = 'Bike'
|
||||
*
|
||||
* getter = {@code List<Goose> 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<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
|
||||
Set<String> propertyNames = new HashSet<String>();
|
||||
|
||||
|
@ -58,4 +58,16 @@ public class Filters {
|
||||
}
|
||||
return setterMethods;
|
||||
}
|
||||
|
||||
public static List<ExecutableElement> adderMethodsIn(Iterable<? extends Element> elements) {
|
||||
List<ExecutableElement> adderMethods = new LinkedList<ExecutableElement>();
|
||||
|
||||
for ( ExecutableElement method : methodsIn( elements ) ) {
|
||||
if ( Executables.isAdderMethod( method ) ) {
|
||||
adderMethods.add( method );
|
||||
}
|
||||
}
|
||||
|
||||
return adderMethods;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
143
processor/src/main/java/org/mapstruct/ap/util/Nouns.java
Normal file
143
processor/src/main/java/org/mapstruct/ap/util/Nouns.java
Normal file
@ -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<ReplaceRule> 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<ReplaceRule> 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 <a href="http://www.eclipse.org/webtools/dali/"></a> 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -33,70 +33,70 @@ import static org.mapstruct.ap.util.Collections.asSet;
|
||||
public class Strings {
|
||||
|
||||
private static final Set<String> 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<String> existingVariableNames) {
|
||||
public static String getSaveVariableName( String name, Collection<String> existingVariableNames ) {
|
||||
name = decapitalize( name );
|
||||
|
||||
Set<String> conflictingNames = new HashSet<String>( KEYWORDS );
|
||||
@ -144,4 +144,5 @@ public class Strings {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
@ -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<Long>( 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() );
|
||||
}
|
||||
|
||||
}
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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<String, Long> PETS_TO_TARGET = ImmutableMap.<String, Long>builder()
|
||||
.put( "rabbit", 1L )
|
||||
.put( "mouse", 2L ).build();
|
||||
|
||||
private static final Map<Long, String> PETS_TO_SOURCE = ImmutableMap.<Long, String>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<Long> toPets( List<String> pets ) throws CatException, DogException {
|
||||
List<Long> result = new ArrayList<Long>();
|
||||
for (String pet : pets) {
|
||||
result.add( toPet( pet) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <T extends Pet> T toPet(String pet, @TargetType Class<T> 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<String> toSourcePets( List<Long> pets ) throws CatException, DogException {
|
||||
List<String> result = new ArrayList<String>();
|
||||
for (Long pet : pets) {
|
||||
result.add( PETS_TO_SOURCE.get( pet ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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<String, Integer> TEETH = ImmutableMap.<String, Integer>builder()
|
||||
.put( "incisor", 1 )
|
||||
.put( "canine", 2 )
|
||||
.put( "moler", 3 ).build();
|
||||
|
||||
public Integer toTooth( String tooth ) {
|
||||
return TEETH.get( tooth );
|
||||
}
|
||||
}
|
@ -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<String> pets;
|
||||
|
||||
public List<String> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void setPets( List<String> pets ) {
|
||||
this.pets = pets;
|
||||
}
|
||||
}
|
@ -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<String> teeth;
|
||||
|
||||
public List<String> getTeeth() {
|
||||
return teeth;
|
||||
}
|
||||
|
||||
public void setTeeth( List<String> teeth ) {
|
||||
this.teeth = teeth;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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<Long> pets;
|
||||
|
||||
public List<Long> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void setPets( List<Long> 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<Long>();
|
||||
}
|
||||
pets.add( pet );
|
||||
}
|
||||
}
|
@ -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<Integer> teeth;
|
||||
|
||||
public List<Integer> getTeeth() {
|
||||
return teeth;
|
||||
}
|
||||
|
||||
public void setTeeth( List<Integer> teeth ) {
|
||||
this.teeth = teeth;
|
||||
}
|
||||
|
||||
public void addTeeth( Integer tooth ) {
|
||||
AdderUsageObserver.setUsed( true );
|
||||
if ( teeth == null ) {
|
||||
teeth = new ArrayList<Integer>();
|
||||
}
|
||||
teeth.add( tooth );
|
||||
}
|
||||
|
||||
}
|
@ -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<Integer> teeth;
|
||||
|
||||
public List<Integer> getTeeth() {
|
||||
return teeth;
|
||||
}
|
||||
|
||||
public void setTeeth( List<Integer> teeth ) {
|
||||
this.teeth = teeth;
|
||||
}
|
||||
|
||||
public void addTooth( Integer pet ) {
|
||||
AdderUsageObserver.setUsed( true );
|
||||
if ( teeth == null ) {
|
||||
teeth = new ArrayList<Integer>();
|
||||
}
|
||||
teeth.add( pet );
|
||||
}
|
||||
|
||||
public void addTeeth( Integer tooth ) {
|
||||
if ( teeth == null ) {
|
||||
teeth = new ArrayList<Integer>();
|
||||
}
|
||||
teeth.add( tooth );
|
||||
}
|
||||
}
|
@ -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<Long> pets;
|
||||
|
||||
public List<Long> 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<Long>();
|
||||
}
|
||||
pets.add( pet );
|
||||
}
|
||||
}
|
@ -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<IndoorPet> pets;
|
||||
|
||||
public List<IndoorPet> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void setPets( List<IndoorPet> pets ) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
public void addPet( IndoorPet pet ) {
|
||||
AdderUsageObserver.setUsed( true );
|
||||
if ( pets == null ) {
|
||||
pets = new ArrayList<IndoorPet>();
|
||||
}
|
||||
pets.add( pet );
|
||||
}
|
||||
}
|
@ -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<Long> pets;
|
||||
|
||||
public List<Long> getPets() {
|
||||
return pets;
|
||||
}
|
||||
|
||||
public void addPet( Long pet ) {
|
||||
AdderUsageObserver.setUsed( true );
|
||||
if ( pets == null ) {
|
||||
pets = new ArrayList<Long>();
|
||||
}
|
||||
pets.add( pet );
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user