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;
|
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.
|
* @return The component model for the generated mapper.
|
||||||
*/
|
*/
|
||||||
String componentModel() default "default";
|
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
|
* @return A constant {@code String} expression specifying the value for the designated target prperty
|
||||||
*/
|
*/
|
||||||
String expression() default "";
|
String expression() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,4 +74,5 @@ public @interface Mapping {
|
|||||||
* @return A constant {@code String} expression specifying the value for the designated target prperty
|
* @return A constant {@code String} expression specifying the value for the designated target prperty
|
||||||
*/
|
*/
|
||||||
String expression() default "";
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.AnnotationMirror;
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
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.Modifier;
|
||||||
import javax.lang.model.element.Name;
|
import javax.lang.model.element.Name;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.element.VariableElement;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
|
||||||
import org.mapstruct.ap.util.Executables;
|
import org.mapstruct.ap.util.Executables;
|
||||||
import org.mapstruct.ap.util.Filters;
|
import org.mapstruct.ap.util.Filters;
|
||||||
|
import org.mapstruct.ap.util.Nouns;
|
||||||
import org.mapstruct.ap.util.TypeUtilsJDK6Fix;
|
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> getters = null;
|
||||||
private List<ExecutableElement> setters = null;
|
private List<ExecutableElement> setters = null;
|
||||||
|
private List<ExecutableElement> adders = null;
|
||||||
private List<ExecutableElement> alternativeTargetAccessors = null;
|
private List<ExecutableElement> alternativeTargetAccessors = null;
|
||||||
|
|
||||||
//CHECKSTYLE:OFF
|
//CHECKSTYLE:OFF
|
||||||
@ -275,6 +276,70 @@ public class Type extends ModelElement implements Comparable<Type> {
|
|||||||
return getters;
|
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
|
* 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
|
* 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
|
* {@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.
|
* 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.
|
* @return an unmodifiable list of alternative target accessors.
|
||||||
*/
|
*/
|
||||||
|
@ -190,6 +190,7 @@ public class Mapping {
|
|||||||
return targetAnnotationValue;
|
return targetAnnotationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Mapping reverse() {
|
public Mapping reverse() {
|
||||||
Mapping reverse = null;
|
Mapping reverse = null;
|
||||||
if ( expression != 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.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
import org.mapstruct.CollectionMappingStrategy;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.Assignment;
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import static org.mapstruct.ap.model.Assignment.AssignmentType.DIRECT;
|
import static org.mapstruct.ap.model.Assignment.AssignmentType.DIRECT;
|
||||||
import static org.mapstruct.ap.model.Assignment.AssignmentType.TYPE_CONVERTED;
|
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.MapperReference;
|
||||||
import org.mapstruct.ap.model.MappingMethod;
|
import org.mapstruct.ap.model.MappingMethod;
|
||||||
import org.mapstruct.ap.model.PropertyMapping;
|
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.AssignmentFactory;
|
||||||
import org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper;
|
import org.mapstruct.ap.model.assignment.GetterCollectionOrMapWrapper;
|
||||||
import org.mapstruct.ap.model.assignment.LocalVarWrapper;
|
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> {
|
public class MapperCreationProcessor implements ModelElementProcessor<List<SourceMethod>, Mapper> {
|
||||||
|
|
||||||
private enum TargetAccessorType { GETTER, SETTER };
|
private enum TargetAccessorType { GETTER, SETTER, ADDER };
|
||||||
|
|
||||||
private Elements elementUtils;
|
private Elements elementUtils;
|
||||||
private Types typeUtils;
|
private Types typeUtils;
|
||||||
@ -108,9 +111,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Mapper getMapper(TypeElement element, List<SourceMethod> methods) {
|
private Mapper getMapper(TypeElement element, List<SourceMethod> methods) {
|
||||||
ReportingPolicy unmappedTargetPolicy = getEffectiveUnmappedTargetPolicy( element );
|
|
||||||
List<MapperReference> mapperReferences = getReferencedMappers( element );
|
List<MapperReference> mapperReferences = getReferencedMappers( element );
|
||||||
List<MappingMethod> mappingMethods = getMappingMethods( mapperReferences, methods, unmappedTargetPolicy );
|
List<MappingMethod> mappingMethods = getMappingMethods( mapperReferences, methods, element );
|
||||||
mappingMethods.addAll( mappingResolver.getVirtualMethodsToGenerate() );
|
mappingMethods.addAll( mappingResolver.getVirtualMethodsToGenerate() );
|
||||||
|
|
||||||
Mapper mapper = new Mapper.Builder()
|
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) {
|
private Decorator getDecorator(TypeElement element, List<SourceMethod> methods) {
|
||||||
DecoratedWithPrism decoratorPrism = DecoratedWithPrism.getInstanceOn( element );
|
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,
|
private List<MappingMethod> getMappingMethods(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||||
ReportingPolicy unmappedTargetPolicy) {
|
TypeElement element ) {
|
||||||
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>();
|
||||||
|
|
||||||
for ( SourceMethod method : methods ) {
|
for ( SourceMethod method : methods ) {
|
||||||
@ -301,7 +308,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
mapperReferences,
|
mapperReferences,
|
||||||
methods,
|
methods,
|
||||||
method,
|
method,
|
||||||
unmappedTargetPolicy
|
element
|
||||||
);
|
);
|
||||||
if ( beanMappingMethod != null ) {
|
if ( beanMappingMethod != null ) {
|
||||||
hasFactoryMethod = beanMappingMethod.getFactoryMethod() != null;
|
hasFactoryMethod = beanMappingMethod.getFactoryMethod() != null;
|
||||||
@ -386,9 +393,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
private PropertyMapping getPropertyMapping(List<MapperReference> mapperReferences,
|
private PropertyMapping getPropertyMapping(List<MapperReference> mapperReferences,
|
||||||
List<SourceMethod> methods,
|
List<SourceMethod> methods,
|
||||||
SourceMethod method,
|
SourceMethod method,
|
||||||
ExecutableElement targetAcessor,
|
ExecutableElement targetAccessor,
|
||||||
|
String targetPropertyName,
|
||||||
Parameter parameter) {
|
Parameter parameter) {
|
||||||
String targetPropertyName = Executables.getPropertyName( targetAcessor );
|
|
||||||
|
|
||||||
// check if there's a mapping defined
|
// check if there's a mapping defined
|
||||||
Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName );
|
Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName );
|
||||||
@ -415,7 +422,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
methods,
|
methods,
|
||||||
method,
|
method,
|
||||||
sourceConstant,
|
sourceConstant,
|
||||||
targetAcessor,
|
targetAccessor,
|
||||||
dateFormat
|
dateFormat
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -435,7 +442,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
method,
|
method,
|
||||||
parameter,
|
parameter,
|
||||||
sourceAccessor,
|
sourceAccessor,
|
||||||
targetAcessor,
|
targetAccessor,
|
||||||
|
targetPropertyName,
|
||||||
dateFormat
|
dateFormat
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -448,7 +456,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
method,
|
method,
|
||||||
parameter,
|
parameter,
|
||||||
sourceAccessor,
|
sourceAccessor,
|
||||||
targetAcessor,
|
targetAccessor,
|
||||||
|
targetPropertyName,
|
||||||
dateFormat
|
dateFormat
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -457,7 +466,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BeanMappingMethod getBeanMappingMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
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>();
|
List<PropertyMapping> propertyMappings = new ArrayList<PropertyMapping>();
|
||||||
Set<String> mappedTargetProperties = new HashSet<String>();
|
Set<String> mappedTargetProperties = new HashSet<String>();
|
||||||
@ -476,10 +490,44 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
|
|
||||||
Mapping mapping = method.getMappingByTargetPropertyName( targetPropertyName );
|
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;
|
PropertyMapping propertyMapping = null;
|
||||||
if ( mapping != null && mapping.getSourceParameterName() != null ) {
|
if ( mapping != null && mapping.getSourceParameterName() != null ) {
|
||||||
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
|
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
|
||||||
propertyMapping = getPropertyMapping( mapperReferences, methods, method, targetAccessor, parameter );
|
propertyMapping = getPropertyMapping(
|
||||||
|
mapperReferences,
|
||||||
|
methods,
|
||||||
|
method,
|
||||||
|
targetAccessor,
|
||||||
|
targetPropertyName,
|
||||||
|
parameter );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( propertyMapping == null ) {
|
if ( propertyMapping == null ) {
|
||||||
@ -489,6 +537,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
methods,
|
methods,
|
||||||
method,
|
method,
|
||||||
targetAccessor,
|
targetAccessor,
|
||||||
|
targetPropertyName,
|
||||||
sourceParameter
|
sourceParameter
|
||||||
);
|
);
|
||||||
if ( propertyMapping != null && newPropertyMapping != null ) {
|
if ( propertyMapping != null && newPropertyMapping != null ) {
|
||||||
@ -657,24 +706,36 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
SourceMethod method,
|
SourceMethod method,
|
||||||
Parameter parameter,
|
Parameter parameter,
|
||||||
ExecutableElement sourceAccessor,
|
ExecutableElement sourceAccessor,
|
||||||
ExecutableElement targetAcessor,
|
ExecutableElement targetAccessor,
|
||||||
|
String targetPropertyName,
|
||||||
String dateFormat) {
|
String dateFormat) {
|
||||||
|
|
||||||
TargetAccessorType targetAccessorType = TargetAccessorType.SETTER;
|
Type sourceType;
|
||||||
Type sourceType = typeFactory.getReturnType( sourceAccessor );
|
|
||||||
Type targetType;
|
Type targetType;
|
||||||
|
TargetAccessorType targetAccessorType;
|
||||||
String sourceReference = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
String sourceReference = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
||||||
if ( Executables.isSetterMethod( targetAcessor ) ) {
|
String iteratorReference = null;
|
||||||
targetType = typeFactory.getSingleParameter( targetAcessor ).getType();
|
if ( Executables.isSetterMethod( targetAccessor ) ) {
|
||||||
|
sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||||
|
targetType = typeFactory.getSingleParameter( targetAccessor ).getType();
|
||||||
|
targetAccessorType = TargetAccessorType.SETTER;
|
||||||
}
|
}
|
||||||
else { // must be getter
|
else if ( Executables.isAdderMethod( targetAccessor ) ) {
|
||||||
targetType = typeFactory.getReturnType( targetAcessor );
|
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;
|
targetAccessorType = TargetAccessorType.GETTER;
|
||||||
}
|
}
|
||||||
|
String sourcePropertyName = Executables.getPropertyName( sourceAccessor );
|
||||||
String targetPropertyName = Executables.getPropertyName( targetAcessor );
|
String mappedElement = "property '" + sourcePropertyName + "'";
|
||||||
|
|
||||||
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
|
||||||
|
|
||||||
Assignment assignment = mappingResolver.getTargetAssignment(
|
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||||
method,
|
method,
|
||||||
@ -685,7 +746,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
targetType,
|
targetType,
|
||||||
targetPropertyName,
|
targetPropertyName,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
sourceReference
|
iteratorReference != null ? iteratorReference : sourceReference
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( assignment != null ) {
|
if ( assignment != null ) {
|
||||||
@ -703,19 +764,15 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
||||||
|
|
||||||
// wrap the setter in the collection / map initializers
|
// wrap the setter in the collection / map initializers
|
||||||
switch ( targetAccessorType ) {
|
if ( targetAccessorType == TargetAccessorType.SETTER ) {
|
||||||
|
// target accessor is setter, so decorate assignment as setter
|
||||||
case GETTER:
|
assignment = new SetterCollectionOrMapWrapper( assignment,
|
||||||
// target accessor is getter, so decorate assignment as getter
|
targetAccessor.getSimpleName().toString() );
|
||||||
assignment = new GetterCollectionOrMapWrapper( assignment,
|
}
|
||||||
targetAcessor.getSimpleName().toString() );
|
else {
|
||||||
break;
|
// target accessor is getter, so decorate assignment as getter
|
||||||
|
assignment = new GetterCollectionOrMapWrapper( assignment,
|
||||||
default: // setter
|
targetAccessor.getSimpleName().toString() );
|
||||||
|
|
||||||
assignment = new SetterCollectionOrMapWrapper( assignment,
|
|
||||||
targetAcessor.getSimpleName().toString() );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For collections and maps include a null check, when the assignment type is DIRECT.
|
// 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 {
|
else {
|
||||||
|
|
||||||
assignment = new SetterWrapper( assignment, method.getThrownTypes() );
|
if ( targetAccessorType == TargetAccessorType.SETTER ) {
|
||||||
if ( !sourceType.isPrimitive() && ( assignment.getType() == TYPE_CONVERTED ) ) {
|
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
|
// for primitive types null check is not possible at all, but a conversion needs
|
||||||
// a null check.
|
// a null check.
|
||||||
assignment = new NullCheckWrapper( assignment );
|
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(
|
String.format(
|
||||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||||
sourceType,
|
sourceType,
|
||||||
Executables.getPropertyName( sourceAccessor ),
|
sourcePropertyName,
|
||||||
targetType,
|
targetType,
|
||||||
Executables.getPropertyName( targetAcessor )
|
targetPropertyName
|
||||||
),
|
),
|
||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return new PropertyMapping(
|
return new PropertyMapping(
|
||||||
parameter.getName(),
|
parameter.getName(),
|
||||||
targetAcessor.getSimpleName().toString(),
|
targetAccessor.getSimpleName().toString(),
|
||||||
targetType,
|
targetType,
|
||||||
assignment
|
assignment
|
||||||
);
|
);
|
||||||
|
@ -70,6 +70,17 @@ public class Executables {
|
|||||||
return false;
|
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) {
|
private static boolean isPublic(ExecutableElement method) {
|
||||||
return method.getModifiers().contains( Modifier.PUBLIC );
|
return method.getModifiers().contains( Modifier.PUBLIC );
|
||||||
}
|
}
|
||||||
@ -94,6 +105,35 @@ public class Executables {
|
|||||||
throw new IllegalArgumentException( "Executable " + getterOrSetterMethod + " is not getter or setter method." );
|
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) {
|
public static Set<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
|
||||||
Set<String> propertyNames = new HashSet<String>();
|
Set<String> propertyNames = new HashSet<String>();
|
||||||
|
|
||||||
|
@ -58,4 +58,16 @@ public class Filters {
|
|||||||
}
|
}
|
||||||
return setterMethods;
|
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.DeclaredType;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
import org.mapstruct.CollectionMappingStrategy;
|
||||||
import org.mapstruct.ap.option.ReportingPolicy;
|
import org.mapstruct.ap.option.ReportingPolicy;
|
||||||
import org.mapstruct.ap.prism.MapperConfigPrism;
|
import org.mapstruct.ap.prism.MapperConfigPrism;
|
||||||
import org.mapstruct.ap.prism.MapperPrism;
|
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.
|
* 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() {
|
public String componentModel() {
|
||||||
if ( !mapperPrism.componentModel().equals( "default" ) ) {
|
if ( !mapperPrism.componentModel().equals( "default" ) ) {
|
||||||
return mapperPrism.componentModel();
|
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 {
|
public class Strings {
|
||||||
|
|
||||||
private static final Set<String> KEYWORDS = asSet(
|
private static final Set<String> KEYWORDS = asSet(
|
||||||
"abstract",
|
"abstract",
|
||||||
"continue",
|
"continue",
|
||||||
"for",
|
"for",
|
||||||
"new",
|
"new",
|
||||||
"switch",
|
"switch",
|
||||||
"assert",
|
"assert",
|
||||||
"default",
|
"default",
|
||||||
"goto",
|
"goto",
|
||||||
"package",
|
"package",
|
||||||
"synchronized",
|
"synchronized",
|
||||||
"boolean",
|
"boolean",
|
||||||
"do",
|
"do",
|
||||||
"if",
|
"if",
|
||||||
"private",
|
"private",
|
||||||
"this",
|
"this",
|
||||||
"break",
|
"break",
|
||||||
"double",
|
"double",
|
||||||
"implements",
|
"implements",
|
||||||
"protected",
|
"protected",
|
||||||
"throw",
|
"throw",
|
||||||
"byte",
|
"byte",
|
||||||
"else",
|
"else",
|
||||||
"import",
|
"import",
|
||||||
"public",
|
"public",
|
||||||
"throws",
|
"throws",
|
||||||
"case",
|
"case",
|
||||||
"enum",
|
"enum",
|
||||||
"instanceof",
|
"instanceof",
|
||||||
"return",
|
"return",
|
||||||
"transient",
|
"transient",
|
||||||
"catch",
|
"catch",
|
||||||
"extends",
|
"extends",
|
||||||
"int",
|
"int",
|
||||||
"short",
|
"short",
|
||||||
"try",
|
"try",
|
||||||
"char",
|
"char",
|
||||||
"final",
|
"final",
|
||||||
"interface",
|
"interface",
|
||||||
"static",
|
"static",
|
||||||
"void",
|
"void",
|
||||||
"class",
|
"class",
|
||||||
"finally",
|
"finally",
|
||||||
"long",
|
"long",
|
||||||
"strictfp",
|
"strictfp",
|
||||||
"volatile",
|
"volatile",
|
||||||
"const",
|
"const",
|
||||||
"float",
|
"float",
|
||||||
"native",
|
"native",
|
||||||
"super",
|
"super",
|
||||||
"while"
|
"while"
|
||||||
);
|
);
|
||||||
|
|
||||||
private Strings() {
|
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 );
|
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 );
|
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();
|
StringBuilder sb = new StringBuilder();
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
|
|
||||||
@ -114,11 +114,11 @@ public class Strings {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEmpty(String string) {
|
public static boolean isEmpty( String string ) {
|
||||||
return string == null || string.isEmpty();
|
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 ) );
|
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
|
* @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
|
* @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 );
|
name = decapitalize( name );
|
||||||
|
|
||||||
Set<String> conflictingNames = new HashSet<String>( KEYWORDS );
|
Set<String> conflictingNames = new HashSet<String>( KEYWORDS );
|
||||||
@ -144,4 +144,5 @@ public class Strings {
|
|||||||
|
|
||||||
return name;
|
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