mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#200 refactoring model, common interface for SimpleAssignment, TypeConversion and MethodReference, introducing decorators
This commit is contained in:
parent
909b5142b7
commit
d412fd3e83
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.TypeConversion;
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,22 +37,18 @@ public interface ConversionProvider {
|
|||||||
/**
|
/**
|
||||||
* Creates the conversion from source to target of a property mapping.
|
* Creates the conversion from source to target of a property mapping.
|
||||||
*
|
*
|
||||||
* @param sourceReference A reference to the source object, e.g.
|
|
||||||
* {@code beanName.getFoo()}.
|
|
||||||
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
||||||
*
|
*
|
||||||
* @return A conversion from source to target.
|
* @return A conversion from source to target.
|
||||||
*/
|
*/
|
||||||
TypeConversion to(String sourceReference, ConversionContext conversionContext);
|
Assignment to(ConversionContext conversionContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the conversion from target to source of a property mapping.
|
* Creates the conversion from target to source of a property mapping.
|
||||||
*
|
*
|
||||||
* @param targetReference A reference to the targetReference object, e.g.
|
|
||||||
* {@code beanName.getFoo()}.
|
|
||||||
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
||||||
*
|
*
|
||||||
* @return A conversion from target to source.
|
* @return A conversion from target to source.
|
||||||
*/
|
*/
|
||||||
TypeConversion from(String targetReference, ConversionContext conversionContext);
|
Assignment from(ConversionContext conversionContext);
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,10 @@ package org.mapstruct.ap.conversion;
|
|||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import org.mapstruct.ap.model.TypeConversion;
|
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
@ -38,23 +37,21 @@ import static org.mapstruct.ap.util.Collections.asSet;
|
|||||||
public class DateToStringConversion implements ConversionProvider {
|
public class DateToStringConversion implements ConversionProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
public Assignment to(ConversionContext conversionContext) {
|
||||||
return new TypeConversion(
|
return AssignmentFactory.createTypeConversion(
|
||||||
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||||
Collections.<Type>emptyList(),
|
Collections.<Type>emptySet(),
|
||||||
getOpenExpression( conversionContext, "format" ),
|
getOpenExpression( conversionContext, "format" ),
|
||||||
sourceReference,
|
getCloseExpression() );
|
||||||
getCloseExpression()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
public Assignment from(ConversionContext conversionContext) {
|
||||||
return new TypeConversion(
|
return AssignmentFactory.createTypeConversion(
|
||||||
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||||
Arrays.asList( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
asSet( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
||||||
getOpenExpression( conversionContext, "parse" ),
|
getOpenExpression( conversionContext, "parse" ),
|
||||||
targetReference,
|
|
||||||
getCloseExpression()
|
getCloseExpression()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.conversion;
|
package org.mapstruct.ap.conversion;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.TypeConversion;
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,12 +40,12 @@ public class ReverseConversion implements ConversionProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
public Assignment to( ConversionContext conversionContext) {
|
||||||
return conversionProvider.from( sourceReference, conversionContext );
|
return conversionProvider.from( conversionContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
public Assignment from(ConversionContext conversionContext) {
|
||||||
return conversionProvider.to( targetReference, conversionContext );
|
return conversionProvider.to( conversionContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,10 @@ package org.mapstruct.ap.conversion;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import org.mapstruct.ap.model.TypeConversion;
|
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
|
import org.mapstruct.ap.model.assignment.TypeConversion;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,24 +34,22 @@ import org.mapstruct.ap.model.common.Type;
|
|||||||
public abstract class SimpleConversion implements ConversionProvider {
|
public abstract class SimpleConversion implements ConversionProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
public Assignment to(ConversionContext conversionContext) {
|
||||||
ConversionExpression toExpressions = getToExpressions( conversionContext );
|
ConversionExpression toExpressions = getToExpressions( conversionContext );
|
||||||
return new TypeConversion(
|
return AssignmentFactory.createTypeConversion(
|
||||||
getToConversionImportTypes( conversionContext ),
|
getToConversionImportTypes( conversionContext ),
|
||||||
Collections.<Type>emptyList(),
|
Collections.<Type>emptySet(),
|
||||||
toExpressions.getOpenExpression(),
|
toExpressions.getOpenExpression(),
|
||||||
sourceReference,
|
|
||||||
toExpressions.getCloseExpression() );
|
toExpressions.getCloseExpression() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
public Assignment from(ConversionContext conversionContext) {
|
||||||
ConversionExpression fromExpressions = getFromExpressions( conversionContext );
|
ConversionExpression fromExpressions = getFromExpressions( conversionContext );
|
||||||
return new TypeConversion(
|
return AssignmentFactory.createTypeConversion(
|
||||||
getFromConversionImportTypes( conversionContext ),
|
getFromConversionImportTypes( conversionContext ),
|
||||||
Collections.<Type>emptyList(),
|
Collections.<Type>emptySet(),
|
||||||
fromExpressions.getOpenExpression(),
|
fromExpressions.getOpenExpression(),
|
||||||
targetReference,
|
|
||||||
fromExpressions.getCloseExpression() );
|
fromExpressions.getCloseExpression() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public interface Assignment {
|
||||||
|
|
||||||
|
Set<Type> getImportTypes();
|
||||||
|
|
||||||
|
Set<Type> getExceptionTypes();
|
||||||
|
|
||||||
|
void setAssignment( Assignment assignment );
|
||||||
|
|
||||||
|
String getSourceReference();
|
||||||
|
|
||||||
|
// TODO: tempfix..
|
||||||
|
boolean isSimple();
|
||||||
|
}
|
@ -38,11 +38,11 @@ import org.mapstruct.ap.model.source.SourceMethod;
|
|||||||
public class BeanMappingMethod extends MappingMethod {
|
public class BeanMappingMethod extends MappingMethod {
|
||||||
|
|
||||||
private final List<PropertyMapping> propertyMappings;
|
private final List<PropertyMapping> propertyMappings;
|
||||||
private final MethodReference factoryMethod;
|
private final Factory factoryMethod;
|
||||||
|
|
||||||
public BeanMappingMethod(SourceMethod method,
|
public BeanMappingMethod(SourceMethod method,
|
||||||
List<PropertyMapping> propertyMappings,
|
List<PropertyMapping> propertyMappings,
|
||||||
MethodReference factoryMethod) {
|
Factory factoryMethod) {
|
||||||
super( method );
|
super( method );
|
||||||
this.propertyMappings = propertyMappings;
|
this.propertyMappings = propertyMappings;
|
||||||
this.factoryMethod = factoryMethod;
|
this.factoryMethod = factoryMethod;
|
||||||
@ -78,7 +78,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getFactoryMethod() {
|
public Factory getFactoryMethod() {
|
||||||
return this.factoryMethod;
|
return this.factoryMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
processor/src/main/java/org/mapstruct/ap/model/Factory.java
Normal file
32
processor/src/main/java/org/mapstruct/ap/model/Factory.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public interface Factory {
|
||||||
|
|
||||||
|
Set<Type> getExceptionTypes();
|
||||||
|
|
||||||
|
}
|
@ -33,11 +33,10 @@ import org.mapstruct.ap.util.Strings;
|
|||||||
*/
|
*/
|
||||||
public class IterableMappingMethod extends MappingMethod {
|
public class IterableMappingMethod extends MappingMethod {
|
||||||
|
|
||||||
private final TargetAssignment elementAssignment;
|
private final Assignment elementAssignment;
|
||||||
private final MethodReference factoryMethod;
|
private final Factory factoryMethod;
|
||||||
|
|
||||||
public IterableMappingMethod(SourceMethod method, TargetAssignment parameterAssignment,
|
public IterableMappingMethod(SourceMethod method, Assignment parameterAssignment, Factory factoryMethod) {
|
||||||
MethodReference factoryMethod) {
|
|
||||||
super( method );
|
super( method );
|
||||||
this.elementAssignment = parameterAssignment;
|
this.elementAssignment = parameterAssignment;
|
||||||
this.factoryMethod = factoryMethod;
|
this.factoryMethod = factoryMethod;
|
||||||
@ -53,7 +52,7 @@ public class IterableMappingMethod extends MappingMethod {
|
|||||||
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetAssignment getElementAssignment() {
|
public Assignment getElementAssignment() {
|
||||||
return elementAssignment;
|
return elementAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +74,7 @@ public class IterableMappingMethod extends MappingMethod {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getFactoryMethod() {
|
public Factory getFactoryMethod() {
|
||||||
return this.factoryMethod;
|
return this.factoryMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,12 +33,12 @@ import org.mapstruct.ap.util.Strings;
|
|||||||
*/
|
*/
|
||||||
public class MapMappingMethod extends MappingMethod {
|
public class MapMappingMethod extends MappingMethod {
|
||||||
|
|
||||||
private final TargetAssignment keyAssignment;
|
private final Assignment keyAssignment;
|
||||||
private final TargetAssignment valueAssignment;
|
private final Assignment valueAssignment;
|
||||||
private final MethodReference factoryMethod;
|
private final Factory factoryMethod;
|
||||||
|
|
||||||
public MapMappingMethod(SourceMethod method, TargetAssignment keyAssignment, TargetAssignment valueAssignment,
|
public MapMappingMethod(SourceMethod method, Assignment keyAssignment, Assignment valueAssignment,
|
||||||
MethodReference factoryMethod) {
|
Factory factoryMethod) {
|
||||||
super( method );
|
super( method );
|
||||||
|
|
||||||
this.keyAssignment = keyAssignment;
|
this.keyAssignment = keyAssignment;
|
||||||
@ -56,11 +56,11 @@ public class MapMappingMethod extends MappingMethod {
|
|||||||
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetAssignment getKeyAssignment() {
|
public Assignment getKeyAssignment() {
|
||||||
return keyAssignment;
|
return keyAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetAssignment getValueAssignment() {
|
public Assignment getValueAssignment() {
|
||||||
return valueAssignment;
|
return valueAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ public class MapMappingMethod extends MappingMethod {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getFactoryMethod() {
|
public Factory getFactoryMethod() {
|
||||||
return this.factoryMethod;
|
return this.factoryMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.mapstruct.ap.model.common.ModelElement;
|
import org.mapstruct.ap.model.common.ModelElement;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.TargetAssignment.AssignmentType;
|
|
||||||
/**
|
/**
|
||||||
* Represents the mapping between a source and target property, e.g. from
|
* Represents the mapping between a source and target property, e.g. from
|
||||||
* {@code String Source#foo} to {@code int Target#bar}. Name and type of source
|
* {@code String Source#foo} to {@code int Target#bar}. Name and type of source
|
||||||
@ -45,12 +44,12 @@ public class PropertyMapping extends ModelElement {
|
|||||||
private final boolean isTargetAccessorSetter;
|
private final boolean isTargetAccessorSetter;
|
||||||
private final String targetReadAccessorName;
|
private final String targetReadAccessorName;
|
||||||
|
|
||||||
private final TargetAssignment propertyAssignment;
|
private final Assignment propertyAssignment;
|
||||||
|
|
||||||
|
|
||||||
public PropertyMapping(String sourceBeanName, String sourceName, String sourceAccessorName, Type sourceType,
|
public PropertyMapping(String sourceBeanName, String sourceName, String sourceAccessorName, Type sourceType,
|
||||||
String targetName, String targetAccessorName, Type targetType,
|
String targetName, String targetAccessorName, Type targetType,
|
||||||
TargetAssignment propertyAssignment ) {
|
Assignment propertyAssignment ) {
|
||||||
|
|
||||||
this.sourceBeanName = sourceBeanName;
|
this.sourceBeanName = sourceBeanName;
|
||||||
this.sourceName = sourceName;
|
this.sourceName = sourceName;
|
||||||
@ -95,7 +94,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
return targetType;
|
return targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetAssignment getPropertyAssignment() {
|
public Assignment getPropertyAssignment() {
|
||||||
return propertyAssignment;
|
return propertyAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,12 +121,12 @@ public class PropertyMapping extends ModelElement {
|
|||||||
Set<Type> importTypes = new HashSet<Type>();
|
Set<Type> importTypes = new HashSet<Type>();
|
||||||
if ( propertyAssignment != null ) {
|
if ( propertyAssignment != null ) {
|
||||||
if ( isTargetAccessorSetter()
|
if ( isTargetAccessorSetter()
|
||||||
&& propertyAssignment.getAssignmentType().equals( AssignmentType.ASSIGNMENT )
|
&& propertyAssignment.isSimple()
|
||||||
&& ( targetType.isCollectionType() || targetType.isMapType() ) ) {
|
&& ( targetType.isCollectionType() || targetType.isMapType() ) ) {
|
||||||
importTypes.addAll( targetType.getImportTypes() );
|
importTypes.addAll( targetType.getImportTypes() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !propertyAssignment.getAssignmentType().equals( AssignmentType.ASSIGNMENT ) ) {
|
if ( !propertyAssignment.isSimple() ) {
|
||||||
importTypes.addAll( propertyAssignment.getImportTypes() );
|
importTypes.addAll( propertyAssignment.getImportTypes() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.mapstruct.ap.model.common.ModelElement;
|
|
||||||
import org.mapstruct.ap.model.common.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class carries the possible ways to do an assignment to a parameter on a mapping target
|
|
||||||
*
|
|
||||||
* The following options exist:
|
|
||||||
* <ol>
|
|
||||||
* <li>MethodReference</li>
|
|
||||||
* <li>TypeConversion</li>
|
|
||||||
* <li>Simple Assignment (empty TargetAssignment)</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @author Sjaak Derksen
|
|
||||||
*/
|
|
||||||
public class TargetAssignment extends ModelElement {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static enum AssignmentType { TYPE_CONVERSION, METHOD_REFERENCE, ASSIGNMENT };
|
|
||||||
|
|
||||||
private MethodReference methodReference;
|
|
||||||
private TypeConversion typeConversion;
|
|
||||||
private final AssignmentType assignmentType;
|
|
||||||
|
|
||||||
|
|
||||||
public TargetAssignment() {
|
|
||||||
assignmentType = AssignmentType.ASSIGNMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TargetAssignment( MethodReference methodReference ) {
|
|
||||||
assignmentType = AssignmentType.METHOD_REFERENCE;
|
|
||||||
this.methodReference = methodReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TargetAssignment( TypeConversion typeConversion ) {
|
|
||||||
assignmentType = AssignmentType.TYPE_CONVERSION;
|
|
||||||
this.typeConversion = typeConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodReference getMethodReference() {
|
|
||||||
return methodReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeConversion getTypeConversion() {
|
|
||||||
return typeConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssignmentType getAssignmentType() {
|
|
||||||
return assignmentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Type> getExceptionTypes() {
|
|
||||||
List<Type> exceptionTypes = new ArrayList<Type>();
|
|
||||||
switch ( assignmentType ) {
|
|
||||||
case METHOD_REFERENCE:
|
|
||||||
// exceptionTypes.addAll( methodReference.getExceptionTypes() );
|
|
||||||
break;
|
|
||||||
case TYPE_CONVERSION:
|
|
||||||
exceptionTypes.addAll( typeConversion.getExceptionTypes() );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return exceptionTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Type> getImportTypes() {
|
|
||||||
Set<Type> importedTypes = new HashSet<Type>();
|
|
||||||
switch ( assignmentType ) {
|
|
||||||
case METHOD_REFERENCE:
|
|
||||||
importedTypes.addAll( methodReference.getImportTypes() );
|
|
||||||
break;
|
|
||||||
case TYPE_CONVERSION:
|
|
||||||
importedTypes.addAll( typeConversion.getImportTypes() );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return importedTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String result = "";
|
|
||||||
switch ( assignmentType ) {
|
|
||||||
case METHOD_REFERENCE:
|
|
||||||
result = methodReference.toString();
|
|
||||||
break;
|
|
||||||
case TYPE_CONVERSION:
|
|
||||||
result = typeConversion.toString();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* 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.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
|
import org.mapstruct.ap.model.common.ModelElement;
|
||||||
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public abstract class AssignmentDecorator extends ModelElement implements Assignment {
|
||||||
|
|
||||||
|
private final Assignment decoratedAssignment;
|
||||||
|
|
||||||
|
public AssignmentDecorator( Assignment decoratedAssignment ) {
|
||||||
|
this.decoratedAssignment = decoratedAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getImportTypes() {
|
||||||
|
return decoratedAssignment.getImportTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getExceptionTypes() {
|
||||||
|
return decoratedAssignment.getExceptionTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAssignment( Assignment assignment ) {
|
||||||
|
decoratedAssignment.setAssignment( assignment );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Assignment getAssignment() {
|
||||||
|
return decoratedAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceReference() {
|
||||||
|
return decoratedAssignment.getSourceReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSimple() {
|
||||||
|
return decoratedAssignment.isSimple();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* 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.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
|
import org.mapstruct.ap.model.Factory;
|
||||||
|
import org.mapstruct.ap.model.MapperReference;
|
||||||
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
import org.mapstruct.ap.model.source.SourceMethod;
|
||||||
|
import org.mapstruct.ap.model.source.builtin.BuiltInMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class AssignmentFactory {
|
||||||
|
|
||||||
|
private AssignmentFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Assignment createTypeConversion( Set<Type> importTypes,
|
||||||
|
Set<Type> exceptionTypes,
|
||||||
|
String openExpression,
|
||||||
|
String closeExpression ) {
|
||||||
|
return new TypeConversion( importTypes, exceptionTypes, openExpression, closeExpression );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Assignment createTypeConversion( String openExpression, String closeExpression ) {
|
||||||
|
return new TypeConversion( Collections.<Type>emptySet(),
|
||||||
|
Collections.<Type>emptySet(),
|
||||||
|
openExpression,
|
||||||
|
closeExpression );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Factory createFactory(SourceMethod method, MapperReference declaringMapper) {
|
||||||
|
return new MethodReference( method, declaringMapper, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Assignment createAssignment(SourceMethod method, MapperReference declaringMapper, Type targetType) {
|
||||||
|
return new MethodReference(method, declaringMapper, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Assignment createAssignment( BuiltInMethod method, ConversionContext contextParam ) {
|
||||||
|
return new MethodReference( method, contextParam );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleAssignment createAssignment( String sourceRef ) {
|
||||||
|
return new SimpleAssignment(sourceRef );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.mapstruct.ap.model.Assignment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class LocalVarDecorator extends AssignmentDecorator {
|
||||||
|
|
||||||
|
public LocalVarDecorator( Assignment decoratedAssignment ) {
|
||||||
|
super( decoratedAssignment );
|
||||||
|
}
|
||||||
|
}
|
@ -16,10 +16,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.model;
|
package org.mapstruct.ap.model.assignment;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
|
import org.mapstruct.ap.model.Factory;
|
||||||
|
import org.mapstruct.ap.model.MapperReference;
|
||||||
|
import org.mapstruct.ap.model.MappingMethod;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
import org.mapstruct.ap.model.common.Parameter;
|
import org.mapstruct.ap.model.common.Parameter;
|
||||||
@ -32,19 +37,11 @@ import org.mapstruct.ap.model.source.builtin.BuiltInMethod;
|
|||||||
*
|
*
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
public class MethodReference extends MappingMethod {
|
public class MethodReference extends MappingMethod implements Assignment, Factory {
|
||||||
|
|
||||||
private final MapperReference declaringMapper;
|
private final MapperReference declaringMapper;
|
||||||
private final Set<Type> importTypes;
|
private final Set<Type> importTypes;
|
||||||
|
|
||||||
/**
|
|
||||||
* A reference to another mapping method or typeConversion in case this is a two-step mapping, e.g. from
|
|
||||||
* {@code JAXBElement<Bar>} to {@code Foo} to for which a nested method call will be generated:
|
|
||||||
* {@code setFoo(barToFoo( jaxbElemToValue( bar) ) )}
|
|
||||||
*/
|
|
||||||
private MethodReference methodRefChild;
|
|
||||||
private TypeConversion typeConversion;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In case this reference targets a built-in method, allows to pass specific context information to the invoked
|
* In case this reference targets a built-in method, allows to pass specific context information to the invoked
|
||||||
* method. Currently this is only used to pass in the configured date format string when invoking a built-in method
|
* method. Currently this is only used to pass in the configured date format string when invoking a built-in method
|
||||||
@ -52,6 +49,14 @@ public class MethodReference extends MappingMethod {
|
|||||||
*/
|
*/
|
||||||
private final String contextParam;
|
private final String contextParam;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to another mapping method or typeConversion in case this is a two-step mapping, e.g. from
|
||||||
|
* {@code JAXBElement<Bar>} to {@code Foo} to for which a nested method call will be generated:
|
||||||
|
* {@code setFoo(barToFoo( jaxbElemToValue( bar) ) )}
|
||||||
|
*/
|
||||||
|
private Assignment assignment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new reference to the given method.
|
* Creates a new reference to the given method.
|
||||||
*
|
*
|
||||||
@ -88,6 +93,20 @@ public class MethodReference extends MappingMethod {
|
|||||||
return contextParam;
|
return contextParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Assignment getAssignment() {
|
||||||
|
return assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAssignment( Assignment assignment ) {
|
||||||
|
this.assignment = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceReference() {
|
||||||
|
return assignment.getSourceReference();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the type of the single source parameter that is not the {@code @TargetType} parameter
|
* @return the type of the single source parameter that is not the {@code @TargetType} parameter
|
||||||
*/
|
*/
|
||||||
@ -100,32 +119,27 @@ public class MethodReference extends MappingMethod {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethodRefChild(MethodReference methodRefChild) {
|
|
||||||
this.methodRefChild = methodRefChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodReference getMethodRefChild() {
|
|
||||||
return methodRefChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypeConversionChild( TypeConversion typeConversion ) {
|
|
||||||
this.typeConversion = typeConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeConversion getTypeConversion() {
|
|
||||||
return typeConversion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Type> getImportTypes() {
|
public Set<Type> getImportTypes() {
|
||||||
Set<Type> imported = super.getImportTypes();
|
Set<Type> imported = new HashSet(super.getImportTypes());
|
||||||
imported.addAll( importTypes );
|
imported.addAll( importTypes );
|
||||||
if ( methodRefChild != null ) {
|
if ( assignment != null ) {
|
||||||
imported.addAll( methodRefChild.getImportTypes() );
|
imported.addAll( assignment.getImportTypes() );
|
||||||
}
|
|
||||||
else if ( typeConversion != null ) {
|
|
||||||
imported.addAll( typeConversion.getImportTypes() );
|
|
||||||
}
|
}
|
||||||
return imported;
|
return imported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getExceptionTypes() {
|
||||||
|
Set<Type> exceptions = new HashSet();
|
||||||
|
if ( assignment != null ) {
|
||||||
|
exceptions.addAll( assignment.getExceptionTypes() );
|
||||||
|
}
|
||||||
|
return exceptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSimple() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.mapstruct.ap.model.Assignment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class NewCollectionOrMapDecorator extends AssignmentDecorator {
|
||||||
|
|
||||||
|
public NewCollectionOrMapDecorator( Assignment decoratedAssignment ) {
|
||||||
|
super( decoratedAssignment );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.mapstruct.ap.model.Assignment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class NullCheckDecorator extends AssignmentDecorator {
|
||||||
|
|
||||||
|
public NullCheckDecorator( Assignment decoratedAssignment ) {
|
||||||
|
super( decoratedAssignment );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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 org.mapstruct.ap.model.Assignment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class SetterDecorator extends AssignmentDecorator {
|
||||||
|
|
||||||
|
public SetterDecorator( Assignment decoratedAssignment ) {
|
||||||
|
super( decoratedAssignment );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* 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.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
|
import org.mapstruct.ap.model.common.ModelElement;
|
||||||
|
import org.mapstruct.ap.model.common.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class SimpleAssignment extends ModelElement implements Assignment {
|
||||||
|
|
||||||
|
private final String sourceReference;
|
||||||
|
|
||||||
|
public SimpleAssignment( String sourceReference ) {
|
||||||
|
this.sourceReference = sourceReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSourceReference() {
|
||||||
|
return sourceReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getImportTypes() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Type> getExceptionTypes() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAssignment( Assignment assignment ) {
|
||||||
|
throw new UnsupportedOperationException( "Not supported." );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSimple() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -16,11 +16,11 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.model;
|
package org.mapstruct.ap.model.assignment;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.common.ModelElement;
|
import org.mapstruct.ap.model.common.ModelElement;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
@ -30,31 +30,30 @@ import org.mapstruct.ap.model.common.Type;
|
|||||||
*
|
*
|
||||||
* @author Gunnar Morling
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
public class TypeConversion extends ModelElement {
|
public class TypeConversion extends ModelElement implements Assignment {
|
||||||
|
|
||||||
|
|
||||||
private final Set<Type> importTypes;
|
private final Set<Type> importTypes;
|
||||||
private final List<Type> exceptionTypes;
|
private final Set<Type> exceptionTypes;
|
||||||
private final String sourceReference;
|
|
||||||
private final String openExpression;
|
private final String openExpression;
|
||||||
private final String closeExpression;
|
private final String closeExpression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reference to mapping method in case this is a two-step mapping, e.g. from
|
* A reference to mapping method in case this is a two-step mapping, e.g. from
|
||||||
* {@code JAXBElement<Bar>} to {@code Foo} to for which a nested method call will be generated:
|
* {@code JAXBElement<Bar>} to {@code Foo} to for which a nested method call will be generated:
|
||||||
* {@code setFoo(barToFoo( jaxbElemToValue( bar) ) )}
|
* {@code setFoo(barToFoo( jaxbElemToValue( bar) ) )}
|
||||||
*/
|
*/
|
||||||
private MethodReference methodRefChild;
|
private Assignment assignment;
|
||||||
|
|
||||||
public TypeConversion( Set<Type> importTypes,
|
|
||||||
List<Type> exceptionTypes,
|
TypeConversion( Set<Type> importTypes,
|
||||||
|
Set<Type> exceptionTypes,
|
||||||
String openExpression,
|
String openExpression,
|
||||||
String sourceReference,
|
|
||||||
String closeExpression ) {
|
String closeExpression ) {
|
||||||
this.importTypes = new HashSet<Type>( importTypes );
|
this.importTypes = new HashSet<Type>( importTypes );
|
||||||
this.importTypes.addAll( exceptionTypes );
|
this.importTypes.addAll( exceptionTypes );
|
||||||
this.exceptionTypes = exceptionTypes;
|
this.exceptionTypes = exceptionTypes;
|
||||||
this.openExpression = openExpression;
|
this.openExpression = openExpression;
|
||||||
this.sourceReference = sourceReference;
|
|
||||||
this.closeExpression = closeExpression;
|
this.closeExpression = closeExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +62,8 @@ public class TypeConversion extends ModelElement {
|
|||||||
return importTypes;
|
return importTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Type> getExceptionTypes() {
|
@Override
|
||||||
|
public Set<Type> getExceptionTypes() {
|
||||||
return exceptionTypes;
|
return exceptionTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,19 +71,26 @@ public class TypeConversion extends ModelElement {
|
|||||||
return openExpression;
|
return openExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSourceReference() {
|
|
||||||
return sourceReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCloseExpression() {
|
public String getCloseExpression() {
|
||||||
return closeExpression;
|
return closeExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethodRefChild( MethodReference methodRefChild ) {
|
public Assignment getAssignment() {
|
||||||
this.methodRefChild = methodRefChild;
|
return assignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getMethodRefChild() {
|
@Override
|
||||||
return methodRefChild;
|
public String getSourceReference() {
|
||||||
|
return assignment.getSourceReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAssignment( Assignment assignment ) {
|
||||||
|
this.assignment = assignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSimple() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Meta-model of assignments
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.model.assignment;
|
@ -19,7 +19,6 @@
|
|||||||
package org.mapstruct.ap.processor;
|
package org.mapstruct.ap.processor;
|
||||||
|
|
||||||
import org.mapstruct.ap.processor.creation.MappingResolver;
|
import org.mapstruct.ap.processor.creation.MappingResolver;
|
||||||
import org.mapstruct.ap.model.TargetAssignment;
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -37,19 +36,25 @@ 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.ap.model.Assignment;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.BeanMappingMethod;
|
import org.mapstruct.ap.model.BeanMappingMethod;
|
||||||
import org.mapstruct.ap.model.Decorator;
|
import org.mapstruct.ap.model.Decorator;
|
||||||
import org.mapstruct.ap.model.DefaultMapperReference;
|
import org.mapstruct.ap.model.DefaultMapperReference;
|
||||||
import org.mapstruct.ap.model.DelegatingMethod;
|
import org.mapstruct.ap.model.DelegatingMethod;
|
||||||
import org.mapstruct.ap.model.EnumMappingMethod;
|
import org.mapstruct.ap.model.EnumMappingMethod;
|
||||||
|
import org.mapstruct.ap.model.Factory;
|
||||||
import org.mapstruct.ap.model.IterableMappingMethod;
|
import org.mapstruct.ap.model.IterableMappingMethod;
|
||||||
import org.mapstruct.ap.model.MapMappingMethod;
|
import org.mapstruct.ap.model.MapMappingMethod;
|
||||||
import org.mapstruct.ap.model.Mapper;
|
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.MethodReference;
|
|
||||||
import org.mapstruct.ap.model.PropertyMapping;
|
import org.mapstruct.ap.model.PropertyMapping;
|
||||||
|
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||||
|
import org.mapstruct.ap.model.assignment.NewCollectionOrMapDecorator;
|
||||||
|
import org.mapstruct.ap.model.assignment.LocalVarDecorator;
|
||||||
|
import org.mapstruct.ap.model.assignment.NullCheckDecorator;
|
||||||
|
import org.mapstruct.ap.model.assignment.SetterDecorator;
|
||||||
import org.mapstruct.ap.model.common.Parameter;
|
import org.mapstruct.ap.model.common.Parameter;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.common.TypeFactory;
|
import org.mapstruct.ap.model.common.TypeFactory;
|
||||||
@ -316,9 +321,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
return mappingMethods;
|
return mappingMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodReference getFactoryMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
private Factory getFactoryMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||||
Type returnType) {
|
Type returnType) {
|
||||||
MethodReference result = null;
|
Factory result = null;
|
||||||
for ( SourceMethod method : methods ) {
|
for ( SourceMethod method : methods ) {
|
||||||
if ( !method.requiresImplementation() && !method.isIterableMapping() && !method.isMapMapping()
|
if ( !method.requiresImplementation() && !method.isIterableMapping() && !method.isMapMapping()
|
||||||
&& method.getSourceParameters().size() == 0 ) {
|
&& method.getSourceParameters().size() == 0 ) {
|
||||||
@ -329,7 +334,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
if ( method.matches( parameterTypes, returnType ) ) {
|
if ( method.matches( parameterTypes, returnType ) ) {
|
||||||
if ( result == null ) {
|
if ( result == null ) {
|
||||||
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
||||||
result = new MethodReference( method, mapperReference, null );
|
result = AssignmentFactory.createFactory( method, mapperReference );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
@ -488,7 +493,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
mappedTargetProperties
|
mappedTargetProperties
|
||||||
);
|
);
|
||||||
|
|
||||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
Factory factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||||
return new BeanMappingMethod( method, propertyMappings, factoryMethod );
|
return new BeanMappingMethod( method, propertyMappings, factoryMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +636,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
String dateFormat) {
|
String dateFormat) {
|
||||||
Type sourceType = typeFactory.getReturnType( sourceAccessor );
|
Type sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||||
Type targetType = null;
|
Type targetType = null;
|
||||||
String conversionString = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
String sourceReference = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
||||||
if ( Executables.isSetterMethod( targetAcessor ) ) {
|
if ( Executables.isSetterMethod( targetAcessor ) ) {
|
||||||
targetType = typeFactory.getSingleParameter( targetAcessor ).getType();
|
targetType = typeFactory.getSingleParameter( targetAcessor ).getType();
|
||||||
}
|
}
|
||||||
@ -643,7 +648,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
|
|
||||||
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
||||||
|
|
||||||
TargetAssignment assignment = mappingResolver.getTargetAssignment(
|
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||||
method,
|
method,
|
||||||
mappedElement,
|
mappedElement,
|
||||||
mapperReferences,
|
mapperReferences,
|
||||||
@ -652,34 +657,51 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
targetType,
|
targetType,
|
||||||
targetPropertyName,
|
targetPropertyName,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
conversionString
|
sourceReference
|
||||||
);
|
);
|
||||||
|
|
||||||
PropertyMapping property = new PropertyMapping(
|
if ( assignment != null ) {
|
||||||
parameter.getName(),
|
|
||||||
Executables.getPropertyName( sourceAccessor ),
|
|
||||||
sourceAccessor.getSimpleName().toString(),
|
|
||||||
sourceType,
|
|
||||||
Executables.getPropertyName( targetAcessor ),
|
|
||||||
targetAcessor.getSimpleName().toString(),
|
|
||||||
targetType,
|
|
||||||
assignment
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( !isPropertyMappable( property ) ) {
|
// target accessor is setter, so decorate assigmment as setter
|
||||||
|
assignment = new SetterDecorator( assignment );
|
||||||
|
|
||||||
|
// create a new Map or Collection implementation if no method or type conversion
|
||||||
|
if ( targetType != null && ( targetType.isCollectionType() || targetType.isMapType() ) ) {
|
||||||
|
if ( assignment.isSimple() ) {
|
||||||
|
assignment = new NewCollectionOrMapDecorator( assignment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decorate assigment with null check of source can be null (is not primitive)
|
||||||
|
if ( !sourceType.isPrimitive() ) {
|
||||||
|
assignment = new NullCheckDecorator( assignment );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||||
property.getSourceType(),
|
sourceType,
|
||||||
property.getSourceName(),
|
Executables.getPropertyName( sourceAccessor ),
|
||||||
property.getTargetType(),
|
targetType,
|
||||||
property.getTargetName()
|
Executables.getPropertyName( targetAcessor )
|
||||||
),
|
),
|
||||||
method.getExecutable()
|
method.getExecutable()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return property;
|
return new PropertyMapping(
|
||||||
|
parameter.getName(),
|
||||||
|
Executables.getPropertyName( sourceAccessor ),
|
||||||
|
sourceAccessor.getSimpleName().toString(),
|
||||||
|
sourceType,
|
||||||
|
Executables.getPropertyName( targetAcessor ),
|
||||||
|
targetAcessor.getSimpleName().toString(),
|
||||||
|
targetType,
|
||||||
|
assignment
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IterableMappingMethod getIterableMappingMethod(List<MapperReference> mapperReferences,
|
private IterableMappingMethod getIterableMappingMethod(List<MapperReference> mapperReferences,
|
||||||
@ -690,7 +712,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
String dateFormat = method.getIterableMapping() != null ? method.getIterableMapping().getDateFormat() : null;
|
String dateFormat = method.getIterableMapping() != null ? method.getIterableMapping().getDateFormat() : null;
|
||||||
String conversionStr = Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() );
|
String conversionStr = Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() );
|
||||||
|
|
||||||
TargetAssignment assignment = mappingResolver.getTargetAssignment(
|
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||||
method,
|
method,
|
||||||
"collection element",
|
"collection element",
|
||||||
mapperReferences,
|
mapperReferences,
|
||||||
@ -714,7 +736,10 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
// target accessor is setter, so decorate assigmment as setter
|
||||||
|
assignment = new SetterDecorator( assignment );
|
||||||
|
|
||||||
|
Factory factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||||
return new IterableMappingMethod( method, assignment, factoryMethod );
|
return new IterableMappingMethod( method, assignment, factoryMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,7 +753,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
Type keyTargetType = resultTypeParams.get( 0 );
|
Type keyTargetType = resultTypeParams.get( 0 );
|
||||||
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
|
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
|
||||||
|
|
||||||
TargetAssignment keyAssignment = mappingResolver.getTargetAssignment(
|
Assignment keyAssignment = mappingResolver.getTargetAssignment(
|
||||||
method,
|
method,
|
||||||
"map key",
|
"map key",
|
||||||
mapperReferences,
|
mapperReferences,
|
||||||
@ -757,7 +782,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
Type valueTargetType = resultTypeParams.get( 1 );
|
Type valueTargetType = resultTypeParams.get( 1 );
|
||||||
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
|
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
|
||||||
|
|
||||||
TargetAssignment valueAssignment = mappingResolver.getTargetAssignment(
|
Assignment valueAssignment = mappingResolver.getTargetAssignment(
|
||||||
method,
|
method,
|
||||||
"map value",
|
"map value",
|
||||||
mapperReferences,
|
mapperReferences,
|
||||||
@ -781,7 +806,11 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
Factory factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||||
|
|
||||||
|
keyAssignment = new LocalVarDecorator( keyAssignment );
|
||||||
|
valueAssignment = new LocalVarDecorator( valueAssignment );
|
||||||
|
|
||||||
return new MapMappingMethod( method, keyAssignment, valueAssignment, factoryMethod );
|
return new MapMappingMethod( method, keyAssignment, valueAssignment, factoryMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,115 +958,4 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the specified property can be mapped from source to target or not. A mapping if possible if one of
|
|
||||||
* the following conditions is true:
|
|
||||||
* <ul>
|
|
||||||
* <li>the source type is assignable to the target type</li>
|
|
||||||
* <li>a mapping method exists</li>
|
|
||||||
* <li>a built-in conversion exists</li>
|
|
||||||
* <li>the property is of a collection or map type and the constructor of the target type (either itself or its
|
|
||||||
* implementation type) accepts the source type.</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param property The property mapping to check.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the specified property can be mapped, {@code false} otherwise.
|
|
||||||
*/
|
|
||||||
private boolean isPropertyMappable(PropertyMapping property) {
|
|
||||||
boolean collectionOrMapTargetTypeHasCompatibleConstructor = false;
|
|
||||||
|
|
||||||
if ( property.getSourceType().isCollectionType() && property.getTargetType().isCollectionType() ) {
|
|
||||||
collectionOrMapTargetTypeHasCompatibleConstructor = collectionTypeHasCompatibleConstructor(
|
|
||||||
property.getSourceType(),
|
|
||||||
property.getTargetType().getImplementationType() != null ?
|
|
||||||
property.getTargetType().getImplementationType() : property.getTargetType()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( property.getSourceType().isMapType() && property.getTargetType().isMapType() ) {
|
|
||||||
collectionOrMapTargetTypeHasCompatibleConstructor = mapTypeHasCompatibleConstructor(
|
|
||||||
property.getSourceType(),
|
|
||||||
property.getTargetType().getImplementationType() != null ?
|
|
||||||
property.getTargetType().getImplementationType() : property.getTargetType()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( property.getPropertyAssignment() != null ||
|
|
||||||
( ( property.getTargetType().isCollectionType() || property.getTargetType().isMapType() ) &&
|
|
||||||
collectionOrMapTargetTypeHasCompatibleConstructor ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the given target type has a single-argument constructor which accepts the given source type.
|
|
||||||
*
|
|
||||||
* @param sourceType the source type
|
|
||||||
* @param targetType the target type
|
|
||||||
*
|
|
||||||
* @return {@code true} if the target type has a constructor accepting the given source type, {@code false}
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
private boolean collectionTypeHasCompatibleConstructor(Type sourceType, Type targetType) {
|
|
||||||
// note (issue #127): actually this should check for the presence of a matching constructor, with help of
|
|
||||||
// Types#asMemberOf(); but this method seems to not work correctly in the Eclipse implementation, so instead we
|
|
||||||
// just check whether the target type is parameterized in a way that it implicitly should have a constructor
|
|
||||||
// which accepts the source type
|
|
||||||
|
|
||||||
TypeMirror sourceElementType = sourceType.getTypeParameters().isEmpty() ?
|
|
||||||
typeFactory.getType( Object.class ).getTypeMirror() :
|
|
||||||
sourceType.getTypeParameters().get( 0 ).getTypeMirror();
|
|
||||||
|
|
||||||
TypeMirror targetElementType = targetType.getTypeParameters().isEmpty() ?
|
|
||||||
typeFactory.getType( Object.class ).getTypeMirror() :
|
|
||||||
targetType.getTypeParameters().get( 0 ).getTypeMirror();
|
|
||||||
|
|
||||||
return typeUtils.isAssignable( sourceElementType, targetElementType );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the given target type has a single-argument constructor which accepts the given source type.
|
|
||||||
*
|
|
||||||
* @param sourceType the source type
|
|
||||||
* @param targetType the target type
|
|
||||||
*
|
|
||||||
* @return {@code true} if the target type has a constructor accepting the given source type, {@code false}
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
private boolean mapTypeHasCompatibleConstructor(Type sourceType, Type targetType) {
|
|
||||||
// note (issue #127): actually this should check for the presence of a matching constructor, with help of
|
|
||||||
// Types#asMemberOf(); but this method seems to not work correctly in the Eclipse implementation, so instead we
|
|
||||||
// just check whether the target type is parameterized in a way that it implicitly should have a constructor
|
|
||||||
// which accepts the source type
|
|
||||||
|
|
||||||
TypeMirror sourceKeyType = null;
|
|
||||||
TypeMirror targetKeyType = null;
|
|
||||||
TypeMirror sourceValueType = null;
|
|
||||||
TypeMirror targetValueType = null;
|
|
||||||
|
|
||||||
if ( sourceType.getTypeParameters().isEmpty() ) {
|
|
||||||
sourceKeyType = typeFactory.getType( Object.class ).getTypeMirror();
|
|
||||||
sourceValueType = typeFactory.getType( Object.class ).getTypeMirror();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sourceKeyType = sourceType.getTypeParameters().get( 0 ).getTypeMirror();
|
|
||||||
sourceValueType = sourceType.getTypeParameters().get( 1 ).getTypeMirror();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( targetType.getTypeParameters().isEmpty() ) {
|
|
||||||
targetKeyType = typeFactory.getType( Object.class ).getTypeMirror();
|
|
||||||
targetValueType = typeFactory.getType( Object.class ).getTypeMirror();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
targetKeyType = targetType.getTypeParameters().get( 0 ).getTypeMirror();
|
|
||||||
targetValueType = targetType.getTypeParameters().get( 1 ).getTypeMirror();
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeUtils.isAssignable( sourceKeyType, targetKeyType ) &&
|
|
||||||
typeUtils.isAssignable( sourceValueType, targetValueType );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,22 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.processor.creation;
|
package org.mapstruct.ap.processor.creation;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.TargetAssignment;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.processing.Messager;
|
import javax.annotation.processing.Messager;
|
||||||
|
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 javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
import org.mapstruct.ap.conversion.ConversionProvider;
|
import org.mapstruct.ap.conversion.ConversionProvider;
|
||||||
import org.mapstruct.ap.conversion.Conversions;
|
import org.mapstruct.ap.conversion.Conversions;
|
||||||
|
import org.mapstruct.ap.model.Assignment;
|
||||||
import org.mapstruct.ap.model.MapperReference;
|
import org.mapstruct.ap.model.MapperReference;
|
||||||
import org.mapstruct.ap.model.MethodReference;
|
import org.mapstruct.ap.model.assignment.SimpleAssignment;
|
||||||
import org.mapstruct.ap.model.TypeConversion;
|
|
||||||
import org.mapstruct.ap.model.VirtualMappingMethod;
|
import org.mapstruct.ap.model.VirtualMappingMethod;
|
||||||
|
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||||
import org.mapstruct.ap.model.common.ConversionContext;
|
import org.mapstruct.ap.model.common.ConversionContext;
|
||||||
import org.mapstruct.ap.model.common.DefaultConversionContext;
|
import org.mapstruct.ap.model.common.DefaultConversionContext;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
@ -71,6 +72,7 @@ public class MappingResolver {
|
|||||||
private final TypeFactory typeFactory;
|
private final TypeFactory typeFactory;
|
||||||
private final Conversions conversions;
|
private final Conversions conversions;
|
||||||
private final BuiltInMappingMethods builtInMethods;
|
private final BuiltInMappingMethods builtInMethods;
|
||||||
|
private final Types typeUtils;
|
||||||
|
|
||||||
private final MethodSelectors methodSelectors;
|
private final MethodSelectors methodSelectors;
|
||||||
/**
|
/**
|
||||||
@ -87,6 +89,7 @@ public class MappingResolver {
|
|||||||
this.builtInMethods = new BuiltInMappingMethods( typeFactory );
|
this.builtInMethods = new BuiltInMappingMethods( typeFactory );
|
||||||
this.virtualMethods = new HashSet<VirtualMappingMethod>();
|
this.virtualMethods = new HashSet<VirtualMappingMethod>();
|
||||||
this.methodSelectors = new MethodSelectors( typeUtils, typeFactory );
|
this.methodSelectors = new MethodSelectors( typeUtils, typeFactory );
|
||||||
|
this.typeUtils = typeUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ public class MappingResolver {
|
|||||||
* <li>null, no assignment found</li>
|
* <li>null, no assignment found</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*/
|
*/
|
||||||
public TargetAssignment getTargetAssignment( SourceMethod mappingMethod,
|
public Assignment getTargetAssignment( SourceMethod mappingMethod,
|
||||||
String mappedElement,
|
String mappedElement,
|
||||||
List<MapperReference> mapperReferences,
|
List<MapperReference> mapperReferences,
|
||||||
List<SourceMethod> methods,
|
List<SourceMethod> methods,
|
||||||
@ -174,52 +177,55 @@ public class MappingResolver {
|
|||||||
this.virtualMethodCandidates = new HashSet<VirtualMappingMethod>();
|
this.virtualMethodCandidates = new HashSet<VirtualMappingMethod>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetAssignment getTargetAssignment( Type sourceType, Type targetType ) {
|
private Assignment getTargetAssignment( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
// first simpele mapping method
|
// first simpele mapping method
|
||||||
MethodReference mappingMethodReference = resolveViaMethod( sourceType, targetType );
|
Assignment referencedMethod = resolveViaMethod( sourceType, targetType );
|
||||||
if ( mappingMethodReference != null ) {
|
if ( referencedMethod != null ) {
|
||||||
|
referencedMethod.setAssignment( AssignmentFactory.createAssignment( sourceReference ) );
|
||||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||||
return new TargetAssignment( mappingMethodReference );
|
return referencedMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then direct assignable
|
// then direct assignable
|
||||||
if ( sourceType.isAssignableTo( targetType ) ) {
|
if ( sourceType.isAssignableTo( targetType ) || context.isPropertyMappable( sourceType, targetType ) ) {
|
||||||
return new TargetAssignment();
|
SimpleAssignment simpleAssignment = AssignmentFactory.createAssignment( sourceReference );
|
||||||
|
return simpleAssignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then type conversion
|
// then type conversion
|
||||||
TypeConversion conversion = resolveViaConversion( sourceType, targetType );
|
Assignment conversion = resolveViaConversion( sourceType, targetType );
|
||||||
if ( conversion != null ) {
|
if ( conversion != null ) {
|
||||||
return new TargetAssignment( conversion );
|
conversion.setAssignment( AssignmentFactory.createAssignment( sourceReference) );
|
||||||
|
return conversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 step method, first: method(method(souurce))
|
// 2 step method, first: method(method(souurce))
|
||||||
mappingMethodReference = resolveViaMethodAndMethod( sourceType, targetType );
|
referencedMethod = resolveViaMethodAndMethod( sourceType, targetType );
|
||||||
if ( mappingMethodReference != null ) {
|
if ( referencedMethod != null ) {
|
||||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||||
return new TargetAssignment( mappingMethodReference );
|
return referencedMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 step method, then: method(conversion(souurce))
|
// 2 step method, then: method(conversion(souurce))
|
||||||
mappingMethodReference = resolveViaConversionAndMethod( sourceType, targetType );
|
referencedMethod = resolveViaConversionAndMethod( sourceType, targetType );
|
||||||
if ( mappingMethodReference != null ) {
|
if ( referencedMethod != null ) {
|
||||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||||
return new TargetAssignment( mappingMethodReference );
|
return referencedMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 step method, finally: conversion(method(souurce))
|
// 2 step method, finally: conversion(method(souurce))
|
||||||
conversion = resolveViaMethodAndConversion( sourceType, targetType );
|
conversion = resolveViaMethodAndConversion( sourceType, targetType );
|
||||||
if ( conversion != null ) {
|
if ( conversion != null ) {
|
||||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||||
return new TargetAssignment( conversion );
|
return conversion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing works, alas, the result is null
|
// if nothing works, alas, the result is null
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeConversion resolveViaConversion( Type sourceType, Type targetType ) {
|
private Assignment resolveViaConversion( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
ConversionProvider conversionProvider = context.conversions.getConversion( sourceType, targetType );
|
ConversionProvider conversionProvider = context.conversions.getConversion( sourceType, targetType );
|
||||||
|
|
||||||
@ -227,10 +233,9 @@ public class MappingResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return conversionProvider.to(
|
ConversionContext ctx = new DefaultConversionContext( context.typeFactory, targetType, dateFormat );
|
||||||
sourceReference,
|
Assignment typeConversion = conversionProvider.to( ctx );
|
||||||
new DefaultConversionContext( context.typeFactory, targetType, dateFormat )
|
return typeConversion;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,7 +243,7 @@ public class MappingResolver {
|
|||||||
* exists.
|
* exists.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private MethodReference resolveViaMethod( Type sourceType, Type targetType ) {
|
private Assignment resolveViaMethod( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
// first try to find a matching source method
|
// first try to find a matching source method
|
||||||
SourceMethod matchingSourceMethod = getBestMatch( methods, sourceType, targetType );
|
SourceMethod matchingSourceMethod = getBestMatch( methods, sourceType, targetType );
|
||||||
@ -254,7 +259,9 @@ public class MappingResolver {
|
|||||||
if ( matchingBuiltInMethod != null ) {
|
if ( matchingBuiltInMethod != null ) {
|
||||||
virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) );
|
virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) );
|
||||||
ConversionContext ctx = new DefaultConversionContext( context.typeFactory, targetType, dateFormat );
|
ConversionContext ctx = new DefaultConversionContext( context.typeFactory, targetType, dateFormat );
|
||||||
return new MethodReference( matchingBuiltInMethod, ctx );
|
Assignment methodReference = AssignmentFactory.createAssignment( matchingBuiltInMethod, ctx );
|
||||||
|
methodReference.setAssignment( AssignmentFactory.createAssignment( sourceReference ) );
|
||||||
|
return methodReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -270,12 +277,12 @@ public class MappingResolver {
|
|||||||
* </ul>
|
* </ul>
|
||||||
* then this method tries to resolve this combination and make a mapping methodY( methodX ( parameter ) )
|
* then this method tries to resolve this combination and make a mapping methodY( methodX ( parameter ) )
|
||||||
*/
|
*/
|
||||||
private MethodReference resolveViaMethodAndMethod( Type sourceType, Type targetType ) {
|
private Assignment resolveViaMethodAndMethod( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
List<Method> methodYCandidates = new ArrayList<Method>( methods );
|
List<Method> methodYCandidates = new ArrayList<Method>( methods );
|
||||||
methodYCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
methodYCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
||||||
|
|
||||||
MethodReference methodRefY = null;
|
Assignment methodRefY = null;
|
||||||
|
|
||||||
// Iterate over all source methods. Check if the return type matches with the parameter that we need.
|
// Iterate over all source methods. Check if the return type matches with the parameter that we need.
|
||||||
// so assume we need a method from A to C we look for a methodX from A to B (all methods in the
|
// so assume we need a method from A to C we look for a methodX from A to B (all methods in the
|
||||||
@ -288,12 +295,13 @@ public class MappingResolver {
|
|||||||
methodRefY = resolveViaMethod( methodYCandidate.getSourceParameters().get( 0 ).getType(),
|
methodRefY = resolveViaMethod( methodYCandidate.getSourceParameters().get( 0 ).getType(),
|
||||||
targetType );
|
targetType );
|
||||||
if ( methodRefY != null ) {
|
if ( methodRefY != null ) {
|
||||||
MethodReference methodRefX = resolveViaMethod(
|
Assignment methodRefX = resolveViaMethod(
|
||||||
sourceType,
|
sourceType,
|
||||||
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
||||||
);
|
);
|
||||||
if ( methodRefX != null ) {
|
if ( methodRefX != null ) {
|
||||||
methodRefY.setMethodRefChild( methodRefX );
|
methodRefY.setAssignment( methodRefX );
|
||||||
|
methodRefX.setAssignment( AssignmentFactory.createAssignment( sourceReference ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -315,12 +323,12 @@ public class MappingResolver {
|
|||||||
* </ul>
|
* </ul>
|
||||||
* then this method tries to resolve this combination and make a mapping methodY( conversionX ( parameter ) )
|
* then this method tries to resolve this combination and make a mapping methodY( conversionX ( parameter ) )
|
||||||
*/
|
*/
|
||||||
private MethodReference resolveViaConversionAndMethod( Type sourceType, Type targetType ) {
|
private Assignment resolveViaConversionAndMethod( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
List<Method> methodYCandidates = new ArrayList<Method>( methods );
|
List<Method> methodYCandidates = new ArrayList<Method>( methods );
|
||||||
methodYCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
methodYCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
||||||
|
|
||||||
MethodReference methodRefY = null;
|
Assignment methodRefY = null;
|
||||||
|
|
||||||
for ( Method methodYCandidate : methodYCandidates ) {
|
for ( Method methodYCandidate : methodYCandidates ) {
|
||||||
if ( methodYCandidate.getSourceParameters().size() == 1 ) {
|
if ( methodYCandidate.getSourceParameters().size() == 1 ) {
|
||||||
@ -329,12 +337,13 @@ public class MappingResolver {
|
|||||||
targetType
|
targetType
|
||||||
);
|
);
|
||||||
if ( methodRefY != null ) {
|
if ( methodRefY != null ) {
|
||||||
TypeConversion conversionXRef = resolveViaConversion(
|
Assignment conversionXRef = resolveViaConversion(
|
||||||
sourceType,
|
sourceType,
|
||||||
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
||||||
);
|
);
|
||||||
if ( conversionXRef != null ) {
|
if ( conversionXRef != null ) {
|
||||||
methodRefY.setTypeConversionChild( conversionXRef );
|
methodRefY.setAssignment( conversionXRef );
|
||||||
|
conversionXRef.setAssignment( new SimpleAssignment( sourceReference ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -356,27 +365,25 @@ public class MappingResolver {
|
|||||||
* </ul>
|
* </ul>
|
||||||
* then this method tries to resolve this combination and make a mapping methodY( conversionX ( parameter ) )
|
* then this method tries to resolve this combination and make a mapping methodY( conversionX ( parameter ) )
|
||||||
*/
|
*/
|
||||||
private TypeConversion resolveViaMethodAndConversion( Type sourceType, Type targetType ) {
|
private Assignment resolveViaMethodAndConversion( Type sourceType, Type targetType ) {
|
||||||
|
|
||||||
List<Method> methodXCandidates = new ArrayList<Method>( methods );
|
List<Method> methodXCandidates = new ArrayList<Method>( methods );
|
||||||
methodXCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
methodXCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
||||||
|
|
||||||
TypeConversion conversionYRef = null;
|
Assignment conversionYRef = null;
|
||||||
|
|
||||||
// search the other way arround
|
// search the other way arround
|
||||||
for ( Method methodXCandidate : methodXCandidates ) {
|
for ( Method methodXCandidate : methodXCandidates ) {
|
||||||
if ( methodXCandidate.getSourceParameters().size() == 1 ) {
|
if ( methodXCandidate.getSourceParameters().size() == 1 ) {
|
||||||
MethodReference methodRefX = resolveViaMethod(
|
Assignment methodRefX = resolveViaMethod(
|
||||||
sourceType,
|
sourceType,
|
||||||
methodXCandidate.getReturnType()
|
methodXCandidate.getReturnType()
|
||||||
);
|
);
|
||||||
if ( methodRefX != null ) {
|
if ( methodRefX != null ) {
|
||||||
conversionYRef = resolveViaConversion(
|
conversionYRef = resolveViaConversion( methodXCandidate.getReturnType(), targetType );
|
||||||
methodXCandidate.getReturnType(),
|
|
||||||
targetType
|
|
||||||
);
|
|
||||||
if ( conversionYRef != null ) {
|
if ( conversionYRef != null ) {
|
||||||
conversionYRef.setMethodRefChild( methodRefX );
|
conversionYRef.setAssignment( methodRefX );
|
||||||
|
methodRefX.setAssignment( new SimpleAssignment( sourceReference ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -423,12 +430,12 @@ public class MappingResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodReference getMappingMethodReference( SourceMethod method,
|
private Assignment getMappingMethodReference( SourceMethod method,
|
||||||
List<MapperReference> mapperReferences,
|
List<MapperReference> mapperReferences,
|
||||||
Type targetType ) {
|
Type targetType ) {
|
||||||
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
||||||
|
|
||||||
return new MethodReference(
|
return AssignmentFactory.createAssignment(
|
||||||
method,
|
method,
|
||||||
mapperReference,
|
mapperReference,
|
||||||
SourceMethod.containsTargetTypeParameter( method.getParameters() ) ? targetType : null
|
SourceMethod.containsTargetTypeParameter( method.getParameters() ) ? targetType : null
|
||||||
@ -444,4 +451,113 @@ public class MappingResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the specified property can be mapped from source to target or not. A mapping if possible if one of
|
||||||
|
* the following conditions is true:
|
||||||
|
* <ul>
|
||||||
|
* <li>the source type is assignable to the target type</li>
|
||||||
|
* <li>a mapping method exists</li>
|
||||||
|
* <li>a built-in conversion exists</li>
|
||||||
|
* <li>the property is of a collection or map type and the constructor of the target type (either itself or its
|
||||||
|
* implementation type) accepts the source type.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param property The property mapping to check.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the specified property can be mapped, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
private boolean isPropertyMappable(Type sourceType, Type targetType) {
|
||||||
|
boolean collectionOrMapTargetTypeHasCompatibleConstructor = false;
|
||||||
|
|
||||||
|
if ( sourceType.isCollectionType() && targetType.isCollectionType() ) {
|
||||||
|
collectionOrMapTargetTypeHasCompatibleConstructor = collectionTypeHasCompatibleConstructor(
|
||||||
|
sourceType,
|
||||||
|
targetType.getImplementationType() != null ?
|
||||||
|
targetType.getImplementationType() : targetType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sourceType.isMapType() && targetType.isMapType() ) {
|
||||||
|
collectionOrMapTargetTypeHasCompatibleConstructor = mapTypeHasCompatibleConstructor(
|
||||||
|
sourceType,
|
||||||
|
targetType.getImplementationType() != null ?
|
||||||
|
targetType.getImplementationType() : targetType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( ( targetType.isCollectionType() || targetType.isMapType() ) &&
|
||||||
|
collectionOrMapTargetTypeHasCompatibleConstructor ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Whether the given target type has a single-argument constructor which accepts the given source type.
|
||||||
|
*
|
||||||
|
* @param sourceType the source type
|
||||||
|
* @param targetType the target type
|
||||||
|
*
|
||||||
|
* @return {@code true} if the target type has a constructor accepting the given source type, {@code false}
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
private boolean collectionTypeHasCompatibleConstructor(Type sourceType, Type targetType) {
|
||||||
|
// note (issue #127): actually this should check for the presence of a matching constructor, with help of
|
||||||
|
// Types#asMemberOf(); but this method seems to not work correctly in the Eclipse implementation, so instead we
|
||||||
|
// just check whether the target type is parameterized in a way that it implicitly should have a constructor
|
||||||
|
// which accepts the source type
|
||||||
|
|
||||||
|
TypeMirror sourceElementType = sourceType.getTypeParameters().isEmpty() ?
|
||||||
|
typeFactory.getType( Object.class ).getTypeMirror() :
|
||||||
|
sourceType.getTypeParameters().get( 0 ).getTypeMirror();
|
||||||
|
|
||||||
|
TypeMirror targetElementType = targetType.getTypeParameters().isEmpty() ?
|
||||||
|
typeFactory.getType( Object.class ).getTypeMirror() :
|
||||||
|
targetType.getTypeParameters().get( 0 ).getTypeMirror();
|
||||||
|
|
||||||
|
return typeUtils.isAssignable( sourceElementType, targetElementType );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given target type has a single-argument constructor which accepts the given source type.
|
||||||
|
*
|
||||||
|
* @param sourceType the source type
|
||||||
|
* @param targetType the target type
|
||||||
|
*
|
||||||
|
* @return {@code true} if the target type has a constructor accepting the given source type, {@code false}
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
private boolean mapTypeHasCompatibleConstructor(Type sourceType, Type targetType) {
|
||||||
|
// note (issue #127): actually this should check for the presence of a matching constructor, with help of
|
||||||
|
// Types#asMemberOf(); but this method seems to not work correctly in the Eclipse implementation, so instead we
|
||||||
|
// just check whether the target type is parameterized in a way that it implicitly should have a constructor
|
||||||
|
// which accepts the source type
|
||||||
|
|
||||||
|
TypeMirror sourceKeyType = null;
|
||||||
|
TypeMirror targetKeyType = null;
|
||||||
|
TypeMirror sourceValueType = null;
|
||||||
|
TypeMirror targetValueType = null;
|
||||||
|
|
||||||
|
if ( sourceType.getTypeParameters().isEmpty() ) {
|
||||||
|
sourceKeyType = typeFactory.getType( Object.class ).getTypeMirror();
|
||||||
|
sourceValueType = typeFactory.getType( Object.class ).getTypeMirror();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sourceKeyType = sourceType.getTypeParameters().get( 0 ).getTypeMirror();
|
||||||
|
sourceValueType = sourceType.getTypeParameters().get( 1 ).getTypeMirror();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( targetType.getTypeParameters().isEmpty() ) {
|
||||||
|
targetKeyType = typeFactory.getType( Object.class ).getTypeMirror();
|
||||||
|
targetValueType = typeFactory.getType( Object.class ).getTypeMirror();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targetKeyType = targetType.getTypeParameters().get( 0 ).getTypeMirror();
|
||||||
|
targetValueType = targetType.getTypeParameters().get( 1 ).getTypeMirror();
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeUtils.isAssignable( sourceKeyType, targetKeyType ) &&
|
||||||
|
typeUtils.isAssignable( sourceValueType, targetValueType );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
for ( <@includeModel object=sourceParameter.type.typeParameters[0]/> ${loopVariableName} : ${sourceParameter.name} ) {
|
for ( <@includeModel object=sourceParameter.type.typeParameters[0]/> ${loopVariableName} : ${sourceParameter.name} ) {
|
||||||
<@includeModel object=elementAssignment target="${resultName}.add" source="${loopVariableName}" targetType="${resultType.typeParameters[0].name}"/>
|
<@includeModel object=elementAssignment target="${resultName}.add" targetType="${resultType.typeParameters[0].name}"/>
|
||||||
}
|
}
|
||||||
<#if returnType.name != "void">
|
<#if returnType.name != "void">
|
||||||
|
|
||||||
|
@ -36,13 +36,11 @@
|
|||||||
<@includeModel object=keyAssignment
|
<@includeModel object=keyAssignment
|
||||||
target=keyVariableName
|
target=keyVariableName
|
||||||
targetType=typeName(resultType.typeParameters[0])
|
targetType=typeName(resultType.typeParameters[0])
|
||||||
source="entry.getKey()"
|
|
||||||
isLocalVar=true/>
|
isLocalVar=true/>
|
||||||
<#-- value -->
|
<#-- value -->
|
||||||
<@includeModel object=valueAssignment
|
<@includeModel object=valueAssignment
|
||||||
target=valueVariableName
|
target=valueVariableName
|
||||||
targetType=typeName(resultType.typeParameters[1])
|
targetType=typeName(resultType.typeParameters[1])
|
||||||
source="entry.getValue()"
|
|
||||||
isLocalVar=true/>
|
isLocalVar=true/>
|
||||||
${resultName}.put( ${keyVariableName}, ${valueVariableName} );
|
${resultName}.put( ${keyVariableName}, ${valueVariableName} );
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,7 @@
|
|||||||
-->
|
-->
|
||||||
<#if !( targetType.collectionType || targetType.mapType ) >
|
<#if !( targetType.collectionType || targetType.mapType ) >
|
||||||
<#-- non collections or maps -->
|
<#-- non collections or maps -->
|
||||||
<#if ( !sourceType.primitive && propertyAssignment.assignmentType!="ASSIGNMENT" ) >
|
<@assignment aTargetType=targetType/>
|
||||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
|
||||||
<@assignmentLine/>
|
|
||||||
}
|
|
||||||
<#else>
|
|
||||||
<@assignmentLine/>
|
|
||||||
</#if>
|
|
||||||
<#else>
|
<#else>
|
||||||
<#-- collections or maps -->
|
<#-- collections or maps -->
|
||||||
<#if ( ext.existingInstanceMapping || !targetAccessorSetter ) >
|
<#if ( ext.existingInstanceMapping || !targetAccessorSetter ) >
|
||||||
@ -34,39 +28,19 @@
|
|||||||
<#if ext.existingInstanceMapping>
|
<#if ext.existingInstanceMapping>
|
||||||
${ext.targetBeanName}.${targetReadAccessorName}().clear();
|
${ext.targetBeanName}.${targetReadAccessorName}().clear();
|
||||||
</#if><#t>
|
</#if><#t>
|
||||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
|
||||||
<#if targetType.collectionType>
|
<#if targetType.collectionType>
|
||||||
<@collectionOrMapAssignmentLine target="${ext.targetBeanName}.${targetReadAccessorName}().addAll"/>
|
<@assignment aTarget="${ext.targetBeanName}.${targetReadAccessorName}().addAll"/>
|
||||||
<#else>
|
<#else>
|
||||||
<@collectionOrMapAssignmentLine target="${ext.targetBeanName}.${targetReadAccessorName}().putAll"/>
|
<@assignment aTarget="${ext.targetBeanName}.${targetReadAccessorName}().putAll"/>
|
||||||
</#if>
|
</#if>
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<#if targetAccessorSetter>
|
<#if targetAccessorSetter>
|
||||||
else if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
else <@assignment/>
|
||||||
<@collectionOrMapAssignmentLine/>
|
|
||||||
}
|
|
||||||
</#if>
|
</#if>
|
||||||
<#elseif targetAccessorSetter>
|
<#elseif targetAccessorSetter>
|
||||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
<@assignment/>
|
||||||
<@collectionOrMapAssignmentLine/>
|
|
||||||
}
|
|
||||||
</#if>
|
</#if>
|
||||||
</#if>
|
</#if>
|
||||||
<#macro collectionOrMapAssignmentLine
|
<#macro assignment aTarget="${ext.targetBeanName}.${targetAccessorName}" aTargetType=targetType>
|
||||||
target="${ext.targetBeanName}.${targetAccessorName}"
|
<@includeModel object=propertyAssignment target=aTarget targetType=aTargetType raw=true/>
|
||||||
source="${sourceBeanName}.${sourceAccessorName}">
|
|
||||||
<#compress>
|
|
||||||
<#if propertyAssignment?? && propertyAssignment.assignmentType!="ASSIGNMENT">
|
|
||||||
<@assignmentLine target source/>
|
|
||||||
<#else>
|
|
||||||
${target}( new <#if targetType.implementationType??><@includeModel object=targetType.implementationType/><#else><@includeModel object=targetType/></#if>( ${source}() ) );
|
|
||||||
</#if>
|
|
||||||
</#compress>
|
|
||||||
|
|
||||||
</#macro>
|
|
||||||
<#macro assignmentLine
|
|
||||||
target="${ext.targetBeanName}.${targetAccessorName}"
|
|
||||||
source="${sourceBeanName}.${sourceAccessorName}">
|
|
||||||
<@includeModel object=propertyAssignment target=target source="${source}()" targetType=targetType raw=true/>
|
|
||||||
</#macro>
|
</#macro>
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
<#--
|
|
||||||
|
|
||||||
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 ( ext.isLocalVar?? && ext.isLocalVar==true )>
|
|
||||||
<#-- assignment is a local variable assignment -->
|
|
||||||
<#if (exceptionTypes?size == 0) >
|
|
||||||
${ext.targetType} ${ext.target} = <@assignment/>;
|
|
||||||
<#else>
|
|
||||||
${ext.targetType} ${ext.target};
|
|
||||||
try {
|
|
||||||
${ext.target} = <@assignment/>;
|
|
||||||
}
|
|
||||||
<#list exceptionTypes as exceptionType>
|
|
||||||
catch ( <@includeModel object=exceptionType/> e ) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
</#list>
|
|
||||||
</#if>
|
|
||||||
<#else>
|
|
||||||
<#-- assignment is a method call -->
|
|
||||||
<#if (exceptionTypes?size == 0) >
|
|
||||||
${ext.target}( <@assignment/> );
|
|
||||||
<#else>
|
|
||||||
try {
|
|
||||||
${ext.target}( <@assignment/> );
|
|
||||||
}
|
|
||||||
<#list exceptionTypes as exceptionType>
|
|
||||||
catch ( <@includeModel object=exceptionType/> e ) {
|
|
||||||
throw new RuntimeException( e );
|
|
||||||
}
|
|
||||||
</#list>
|
|
||||||
</#if>
|
|
||||||
</#if>
|
|
||||||
<#macro assignment>
|
|
||||||
<#compress>
|
|
||||||
<#switch assignmentType>
|
|
||||||
<#case "TYPE_CONVERSION">
|
|
||||||
<@includeModel object=typeConversion source="${ext.source}" targetType=ext.targetType/>
|
|
||||||
<#break>
|
|
||||||
<#case "METHOD_REFERENCE">
|
|
||||||
<@includeModel object=methodReference source="${ext.source}" targetType=ext.targetType raw=ext.raw/>
|
|
||||||
<#break>
|
|
||||||
<#case "ASSIGNMENT">
|
|
||||||
${ext.source}
|
|
||||||
<#break>
|
|
||||||
</#switch>
|
|
||||||
</#compress>
|
|
||||||
</#macro>
|
|
@ -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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<#if (exceptionTypes?size == 0) >
|
||||||
|
${ext.targetType} ${ext.target} = <@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/>;
|
||||||
|
<#else>
|
||||||
|
${ext.targetType} ${ext.target};
|
||||||
|
try {
|
||||||
|
${ext.target} = <@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/>;
|
||||||
|
}
|
||||||
|
<#list exceptionTypes as exceptionType>
|
||||||
|
catch ( <@includeModel object=exceptionType/> e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
</#list>
|
||||||
|
</#if>
|
@ -27,20 +27,11 @@
|
|||||||
<#-- a class is passed on for casting, see @TargetType -->
|
<#-- a class is passed on for casting, see @TargetType -->
|
||||||
${ext.targetType}.class
|
${ext.targetType}.class
|
||||||
<#else>
|
<#else>
|
||||||
<#if methodRefChild??>
|
<@includeModel object=assignment targetType=singleSourceParameterType raw=ext.raw/>
|
||||||
<#-- the nested case: another method -->
|
|
||||||
<@includeModel object=methodRefChild source=ext.source targetType=singleSourceParameterType.name/>
|
|
||||||
<#elseif typeConversion??>
|
|
||||||
<#-- the nested case: a type conversion -->
|
|
||||||
<@includeModel object=typeConversion source=ext.source targetType=singleSourceParameterType.name/>
|
|
||||||
<#else>
|
|
||||||
<#-- the non nested case -->
|
|
||||||
${ext.source}
|
|
||||||
</#if>
|
|
||||||
</#if>
|
</#if>
|
||||||
<#if param_has_next>, </#if>
|
<#if param_has_next>, </#if>
|
||||||
</#list>
|
</#list>
|
||||||
<#-- context parameter, e.g. for buildin methods concerning date conversion -->
|
<#-- context parameter, e.g. for builtin methods concerning date conversion -->
|
||||||
<#if contextParam??>, ${contextParam}</#if>
|
<#if contextParam??>, ${contextParam}</#if>
|
||||||
</#macro>
|
</#macro>
|
||||||
</@compress>
|
</@compress>
|
@ -18,10 +18,4 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<#if methodRefChild??>
|
${ext.target}( new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/></#if>( ${sourceReference} ) );
|
||||||
<#-- the nested case: mapping method -->
|
|
||||||
${openExpression}<@includeModel object=methodRefChild source=ext.source targetType=ext.targetType/>${closeExpression}
|
|
||||||
<#else>
|
|
||||||
<#-- the non nested case: a type conversion -->
|
|
||||||
${openExpression}${sourceReference}${closeExpression}
|
|
||||||
</#if>
|
|
@ -0,0 +1,23 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
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 ( ${sourceReference} != null ) {
|
||||||
|
<@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/>
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
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) >
|
||||||
|
${ext.target}( <@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/> );
|
||||||
|
<#else>
|
||||||
|
try {
|
||||||
|
${ext.target}( <@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/> );
|
||||||
|
}
|
||||||
|
<#list exceptionTypes as exceptionType>
|
||||||
|
catch ( <@includeModel object=exceptionType/> e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
</#list>
|
||||||
|
</#if>
|
@ -0,0 +1,21 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
${sourceReference}
|
@ -0,0 +1,21 @@
|
|||||||
|
<#--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
${openExpression}<@includeModel object=assignment target=ext.target targetType=ext.targetType raw=ext.raw/>${closeExpression}
|
Loading…
x
Reference in New Issue
Block a user