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;
|
||||
|
||||
import org.mapstruct.ap.model.TypeConversion;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
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.
|
||||
*
|
||||
* @param sourceReference A reference to the source object, e.g.
|
||||
* {@code beanName.getFoo()}.
|
||||
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param targetReference A reference to the targetReference object, e.g.
|
||||
* {@code beanName.getFoo()}.
|
||||
* @param conversionContext ConversionContext providing optional information required for creating the conversion.
|
||||
*
|
||||
* @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.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.mapstruct.ap.model.TypeConversion;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||
import org.mapstruct.ap.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.model.common.Type;
|
||||
|
||||
@ -38,23 +37,21 @@ import static org.mapstruct.ap.util.Collections.asSet;
|
||||
public class DateToStringConversion implements ConversionProvider {
|
||||
|
||||
@Override
|
||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
||||
return new TypeConversion(
|
||||
public Assignment to(ConversionContext conversionContext) {
|
||||
return AssignmentFactory.createTypeConversion(
|
||||
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||
Collections.<Type>emptyList(),
|
||||
Collections.<Type>emptySet(),
|
||||
getOpenExpression( conversionContext, "format" ),
|
||||
sourceReference,
|
||||
getCloseExpression()
|
||||
);
|
||||
getCloseExpression() );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
||||
return new TypeConversion(
|
||||
public Assignment from(ConversionContext conversionContext) {
|
||||
return AssignmentFactory.createTypeConversion(
|
||||
asSet( conversionContext.getTypeFactory().getType( SimpleDateFormat.class ) ),
|
||||
Arrays.asList( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
||||
asSet( conversionContext.getTypeFactory().getType( ParseException.class ) ),
|
||||
getOpenExpression( conversionContext, "parse" ),
|
||||
targetReference,
|
||||
getCloseExpression()
|
||||
);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
package org.mapstruct.ap.conversion;
|
||||
|
||||
import org.mapstruct.ap.model.TypeConversion;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
import org.mapstruct.ap.model.common.ConversionContext;
|
||||
|
||||
/**
|
||||
@ -40,12 +40,12 @@ public class ReverseConversion implements ConversionProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
||||
return conversionProvider.from( sourceReference, conversionContext );
|
||||
public Assignment to( ConversionContext conversionContext) {
|
||||
return conversionProvider.from( conversionContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
||||
return conversionProvider.to( targetReference, conversionContext );
|
||||
public Assignment from(ConversionContext conversionContext) {
|
||||
return conversionProvider.to( conversionContext );
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,10 @@ package org.mapstruct.ap.conversion;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.model.TypeConversion;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
import org.mapstruct.ap.model.assignment.AssignmentFactory;
|
||||
import org.mapstruct.ap.model.common.ConversionContext;
|
||||
import org.mapstruct.ap.model.assignment.TypeConversion;
|
||||
import org.mapstruct.ap.model.common.Type;
|
||||
|
||||
/**
|
||||
@ -33,24 +34,22 @@ import org.mapstruct.ap.model.common.Type;
|
||||
public abstract class SimpleConversion implements ConversionProvider {
|
||||
|
||||
@Override
|
||||
public TypeConversion to(String sourceReference, ConversionContext conversionContext) {
|
||||
public Assignment to(ConversionContext conversionContext) {
|
||||
ConversionExpression toExpressions = getToExpressions( conversionContext );
|
||||
return new TypeConversion(
|
||||
return AssignmentFactory.createTypeConversion(
|
||||
getToConversionImportTypes( conversionContext ),
|
||||
Collections.<Type>emptyList(),
|
||||
Collections.<Type>emptySet(),
|
||||
toExpressions.getOpenExpression(),
|
||||
sourceReference,
|
||||
toExpressions.getCloseExpression() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConversion from(String targetReference, ConversionContext conversionContext) {
|
||||
public Assignment from(ConversionContext conversionContext) {
|
||||
ConversionExpression fromExpressions = getFromExpressions( conversionContext );
|
||||
return new TypeConversion(
|
||||
return AssignmentFactory.createTypeConversion(
|
||||
getFromConversionImportTypes( conversionContext ),
|
||||
Collections.<Type>emptyList(),
|
||||
Collections.<Type>emptySet(),
|
||||
fromExpressions.getOpenExpression(),
|
||||
targetReference,
|
||||
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 {
|
||||
|
||||
private final List<PropertyMapping> propertyMappings;
|
||||
private final MethodReference factoryMethod;
|
||||
private final Factory factoryMethod;
|
||||
|
||||
public BeanMappingMethod(SourceMethod method,
|
||||
List<PropertyMapping> propertyMappings,
|
||||
MethodReference factoryMethod) {
|
||||
Factory factoryMethod) {
|
||||
super( method );
|
||||
this.propertyMappings = propertyMappings;
|
||||
this.factoryMethod = factoryMethod;
|
||||
@ -78,7 +78,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
return types;
|
||||
}
|
||||
|
||||
public MethodReference getFactoryMethod() {
|
||||
public Factory getFactoryMethod() {
|
||||
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 {
|
||||
|
||||
private final TargetAssignment elementAssignment;
|
||||
private final MethodReference factoryMethod;
|
||||
private final Assignment elementAssignment;
|
||||
private final Factory factoryMethod;
|
||||
|
||||
public IterableMappingMethod(SourceMethod method, TargetAssignment parameterAssignment,
|
||||
MethodReference factoryMethod) {
|
||||
public IterableMappingMethod(SourceMethod method, Assignment parameterAssignment, Factory factoryMethod) {
|
||||
super( method );
|
||||
this.elementAssignment = parameterAssignment;
|
||||
this.factoryMethod = factoryMethod;
|
||||
@ -53,7 +52,7 @@ public class IterableMappingMethod extends MappingMethod {
|
||||
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
||||
}
|
||||
|
||||
public TargetAssignment getElementAssignment() {
|
||||
public Assignment getElementAssignment() {
|
||||
return elementAssignment;
|
||||
}
|
||||
|
||||
@ -75,7 +74,7 @@ public class IterableMappingMethod extends MappingMethod {
|
||||
);
|
||||
}
|
||||
|
||||
public MethodReference getFactoryMethod() {
|
||||
public Factory getFactoryMethod() {
|
||||
return this.factoryMethod;
|
||||
}
|
||||
}
|
||||
|
@ -33,12 +33,12 @@ import org.mapstruct.ap.util.Strings;
|
||||
*/
|
||||
public class MapMappingMethod extends MappingMethod {
|
||||
|
||||
private final TargetAssignment keyAssignment;
|
||||
private final TargetAssignment valueAssignment;
|
||||
private final MethodReference factoryMethod;
|
||||
private final Assignment keyAssignment;
|
||||
private final Assignment valueAssignment;
|
||||
private final Factory factoryMethod;
|
||||
|
||||
public MapMappingMethod(SourceMethod method, TargetAssignment keyAssignment, TargetAssignment valueAssignment,
|
||||
MethodReference factoryMethod) {
|
||||
public MapMappingMethod(SourceMethod method, Assignment keyAssignment, Assignment valueAssignment,
|
||||
Factory factoryMethod) {
|
||||
super( method );
|
||||
|
||||
this.keyAssignment = keyAssignment;
|
||||
@ -56,11 +56,11 @@ public class MapMappingMethod extends MappingMethod {
|
||||
throw new IllegalStateException( "Method " + this + " has no source parameter." );
|
||||
}
|
||||
|
||||
public TargetAssignment getKeyAssignment() {
|
||||
public Assignment getKeyAssignment() {
|
||||
return keyAssignment;
|
||||
}
|
||||
|
||||
public TargetAssignment getValueAssignment() {
|
||||
public Assignment getValueAssignment() {
|
||||
return valueAssignment;
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ public class MapMappingMethod extends MappingMethod {
|
||||
);
|
||||
}
|
||||
|
||||
public MethodReference getFactoryMethod() {
|
||||
public Factory getFactoryMethod() {
|
||||
return this.factoryMethod;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ import java.util.Set;
|
||||
|
||||
import org.mapstruct.ap.model.common.ModelElement;
|
||||
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
|
||||
* {@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 String targetReadAccessorName;
|
||||
|
||||
private final TargetAssignment propertyAssignment;
|
||||
private final Assignment propertyAssignment;
|
||||
|
||||
|
||||
public PropertyMapping(String sourceBeanName, String sourceName, String sourceAccessorName, Type sourceType,
|
||||
String targetName, String targetAccessorName, Type targetType,
|
||||
TargetAssignment propertyAssignment ) {
|
||||
Assignment propertyAssignment ) {
|
||||
|
||||
this.sourceBeanName = sourceBeanName;
|
||||
this.sourceName = sourceName;
|
||||
@ -95,7 +94,7 @@ public class PropertyMapping extends ModelElement {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public TargetAssignment getPropertyAssignment() {
|
||||
public Assignment getPropertyAssignment() {
|
||||
return propertyAssignment;
|
||||
}
|
||||
|
||||
@ -122,12 +121,12 @@ public class PropertyMapping extends ModelElement {
|
||||
Set<Type> importTypes = new HashSet<Type>();
|
||||
if ( propertyAssignment != null ) {
|
||||
if ( isTargetAccessorSetter()
|
||||
&& propertyAssignment.getAssignmentType().equals( AssignmentType.ASSIGNMENT )
|
||||
&& propertyAssignment.isSimple()
|
||||
&& ( targetType.isCollectionType() || targetType.isMapType() ) ) {
|
||||
importTypes.addAll( targetType.getImportTypes() );
|
||||
}
|
||||
|
||||
if ( !propertyAssignment.getAssignmentType().equals( AssignmentType.ASSIGNMENT ) ) {
|
||||
if ( !propertyAssignment.isSimple() ) {
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.model;
|
||||
package org.mapstruct.ap.model.assignment;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
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.Parameter;
|
||||
@ -32,19 +37,11 @@ import org.mapstruct.ap.model.source.builtin.BuiltInMethod;
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class MethodReference extends MappingMethod {
|
||||
public class MethodReference extends MappingMethod implements Assignment, Factory {
|
||||
|
||||
private final MapperReference declaringMapper;
|
||||
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
|
||||
* 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;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -88,6 +93,20 @@ public class MethodReference extends MappingMethod {
|
||||
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
|
||||
*/
|
||||
@ -100,32 +119,27 @@ public class MethodReference extends MappingMethod {
|
||||
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
|
||||
public Set<Type> getImportTypes() {
|
||||
Set<Type> imported = super.getImportTypes();
|
||||
Set<Type> imported = new HashSet(super.getImportTypes());
|
||||
imported.addAll( importTypes );
|
||||
if ( methodRefChild != null ) {
|
||||
imported.addAll( methodRefChild.getImportTypes() );
|
||||
}
|
||||
else if ( typeConversion != null ) {
|
||||
imported.addAll( typeConversion.getImportTypes() );
|
||||
if ( assignment != null ) {
|
||||
imported.addAll( assignment.getImportTypes() );
|
||||
}
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.model;
|
||||
package org.mapstruct.ap.model.assignment;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
|
||||
import org.mapstruct.ap.model.common.ModelElement;
|
||||
import org.mapstruct.ap.model.common.Type;
|
||||
@ -30,31 +30,30 @@ import org.mapstruct.ap.model.common.Type;
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class TypeConversion extends ModelElement {
|
||||
public class TypeConversion extends ModelElement implements Assignment {
|
||||
|
||||
|
||||
private final Set<Type> importTypes;
|
||||
private final List<Type> exceptionTypes;
|
||||
private final String sourceReference;
|
||||
private final Set<Type> exceptionTypes;
|
||||
private final String openExpression;
|
||||
private final String closeExpression;
|
||||
|
||||
/**
|
||||
* 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 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 sourceReference,
|
||||
String closeExpression ) {
|
||||
this.importTypes = new HashSet<Type>( importTypes );
|
||||
this.importTypes.addAll( exceptionTypes );
|
||||
this.exceptionTypes = exceptionTypes;
|
||||
this.openExpression = openExpression;
|
||||
this.sourceReference = sourceReference;
|
||||
this.closeExpression = closeExpression;
|
||||
}
|
||||
|
||||
@ -63,7 +62,8 @@ public class TypeConversion extends ModelElement {
|
||||
return importTypes;
|
||||
}
|
||||
|
||||
public List<Type> getExceptionTypes() {
|
||||
@Override
|
||||
public Set<Type> getExceptionTypes() {
|
||||
return exceptionTypes;
|
||||
}
|
||||
|
||||
@ -71,19 +71,26 @@ public class TypeConversion extends ModelElement {
|
||||
return openExpression;
|
||||
}
|
||||
|
||||
public String getSourceReference() {
|
||||
return sourceReference;
|
||||
}
|
||||
|
||||
public String getCloseExpression() {
|
||||
return closeExpression;
|
||||
}
|
||||
|
||||
public void setMethodRefChild( MethodReference methodRefChild ) {
|
||||
this.methodRefChild = methodRefChild;
|
||||
public Assignment getAssignment() {
|
||||
return assignment;
|
||||
}
|
||||
|
||||
public MethodReference getMethodRefChild() {
|
||||
return methodRefChild;
|
||||
@Override
|
||||
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;
|
||||
|
||||
import org.mapstruct.ap.processor.creation.MappingResolver;
|
||||
import org.mapstruct.ap.model.TargetAssignment;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
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.Types;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
|
||||
import org.mapstruct.ap.model.BeanMappingMethod;
|
||||
import org.mapstruct.ap.model.Decorator;
|
||||
import org.mapstruct.ap.model.DefaultMapperReference;
|
||||
import org.mapstruct.ap.model.DelegatingMethod;
|
||||
import org.mapstruct.ap.model.EnumMappingMethod;
|
||||
import org.mapstruct.ap.model.Factory;
|
||||
import org.mapstruct.ap.model.IterableMappingMethod;
|
||||
import org.mapstruct.ap.model.MapMappingMethod;
|
||||
import org.mapstruct.ap.model.Mapper;
|
||||
import org.mapstruct.ap.model.MapperReference;
|
||||
import org.mapstruct.ap.model.MappingMethod;
|
||||
import org.mapstruct.ap.model.MethodReference;
|
||||
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.Type;
|
||||
import org.mapstruct.ap.model.common.TypeFactory;
|
||||
@ -316,9 +321,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
return mappingMethods;
|
||||
}
|
||||
|
||||
private MethodReference getFactoryMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||
private Factory getFactoryMethod(List<MapperReference> mapperReferences, List<SourceMethod> methods,
|
||||
Type returnType) {
|
||||
MethodReference result = null;
|
||||
Factory result = null;
|
||||
for ( SourceMethod method : methods ) {
|
||||
if ( !method.requiresImplementation() && !method.isIterableMapping() && !method.isMapMapping()
|
||||
&& method.getSourceParameters().size() == 0 ) {
|
||||
@ -329,7 +334,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
if ( method.matches( parameterTypes, returnType ) ) {
|
||||
if ( result == null ) {
|
||||
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
||||
result = new MethodReference( method, mapperReference, null );
|
||||
result = AssignmentFactory.createFactory( method, mapperReference );
|
||||
}
|
||||
else {
|
||||
messager.printMessage(
|
||||
@ -488,7 +493,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
mappedTargetProperties
|
||||
);
|
||||
|
||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||
Factory factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||
return new BeanMappingMethod( method, propertyMappings, factoryMethod );
|
||||
}
|
||||
|
||||
@ -631,7 +636,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
String dateFormat) {
|
||||
Type sourceType = typeFactory.getReturnType( sourceAccessor );
|
||||
Type targetType = null;
|
||||
String conversionString = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
||||
String sourceReference = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()";
|
||||
if ( Executables.isSetterMethod( targetAcessor ) ) {
|
||||
targetType = typeFactory.getSingleParameter( targetAcessor ).getType();
|
||||
}
|
||||
@ -643,7 +648,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
|
||||
String mappedElement = "property '" + Executables.getPropertyName( sourceAccessor ) + "'";
|
||||
|
||||
TargetAssignment assignment = mappingResolver.getTargetAssignment(
|
||||
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||
method,
|
||||
mappedElement,
|
||||
mapperReferences,
|
||||
@ -652,34 +657,51 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
targetType,
|
||||
targetPropertyName,
|
||||
dateFormat,
|
||||
conversionString
|
||||
sourceReference
|
||||
);
|
||||
|
||||
PropertyMapping property = new PropertyMapping(
|
||||
parameter.getName(),
|
||||
Executables.getPropertyName( sourceAccessor ),
|
||||
sourceAccessor.getSimpleName().toString(),
|
||||
sourceType,
|
||||
Executables.getPropertyName( targetAcessor ),
|
||||
targetAcessor.getSimpleName().toString(),
|
||||
targetType,
|
||||
assignment
|
||||
);
|
||||
if ( assignment != null ) {
|
||||
|
||||
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(
|
||||
Kind.ERROR,
|
||||
String.format(
|
||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||
property.getSourceType(),
|
||||
property.getSourceName(),
|
||||
property.getTargetType(),
|
||||
property.getTargetName()
|
||||
),
|
||||
method.getExecutable()
|
||||
Kind.ERROR,
|
||||
String.format(
|
||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||
sourceType,
|
||||
Executables.getPropertyName( sourceAccessor ),
|
||||
targetType,
|
||||
Executables.getPropertyName( targetAcessor )
|
||||
),
|
||||
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,
|
||||
@ -690,7 +712,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
String dateFormat = method.getIterableMapping() != null ? method.getIterableMapping().getDateFormat() : null;
|
||||
String conversionStr = Strings.getSaveVariableName( sourceElementType.getName(), method.getParameterNames() );
|
||||
|
||||
TargetAssignment assignment = mappingResolver.getTargetAssignment(
|
||||
Assignment assignment = mappingResolver.getTargetAssignment(
|
||||
method,
|
||||
"collection element",
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -728,7 +753,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
Type keyTargetType = resultTypeParams.get( 0 );
|
||||
String keyDateFormat = method.getMapMapping() != null ? method.getMapMapping().getKeyFormat() : null;
|
||||
|
||||
TargetAssignment keyAssignment = mappingResolver.getTargetAssignment(
|
||||
Assignment keyAssignment = mappingResolver.getTargetAssignment(
|
||||
method,
|
||||
"map key",
|
||||
mapperReferences,
|
||||
@ -757,7 +782,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
Type valueTargetType = resultTypeParams.get( 1 );
|
||||
String valueDateFormat = method.getMapMapping() != null ? method.getMapMapping().getValueFormat() : null;
|
||||
|
||||
TargetAssignment valueAssignment = mappingResolver.getTargetAssignment(
|
||||
Assignment valueAssignment = mappingResolver.getTargetAssignment(
|
||||
method,
|
||||
"map value",
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -929,115 +958,4 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
}
|
||||
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;
|
||||
|
||||
import org.mapstruct.ap.model.TargetAssignment;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.processing.Messager;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import org.mapstruct.ap.conversion.ConversionProvider;
|
||||
import org.mapstruct.ap.conversion.Conversions;
|
||||
import org.mapstruct.ap.model.Assignment;
|
||||
import org.mapstruct.ap.model.MapperReference;
|
||||
import org.mapstruct.ap.model.MethodReference;
|
||||
import org.mapstruct.ap.model.TypeConversion;
|
||||
import org.mapstruct.ap.model.assignment.SimpleAssignment;
|
||||
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.DefaultConversionContext;
|
||||
import org.mapstruct.ap.model.common.Type;
|
||||
@ -71,6 +72,7 @@ public class MappingResolver {
|
||||
private final TypeFactory typeFactory;
|
||||
private final Conversions conversions;
|
||||
private final BuiltInMappingMethods builtInMethods;
|
||||
private final Types typeUtils;
|
||||
|
||||
private final MethodSelectors methodSelectors;
|
||||
/**
|
||||
@ -87,6 +89,7 @@ public class MappingResolver {
|
||||
this.builtInMethods = new BuiltInMappingMethods( typeFactory );
|
||||
this.virtualMethods = new HashSet<VirtualMappingMethod>();
|
||||
this.methodSelectors = new MethodSelectors( typeUtils, typeFactory );
|
||||
this.typeUtils = typeUtils;
|
||||
}
|
||||
|
||||
|
||||
@ -111,7 +114,7 @@ public class MappingResolver {
|
||||
* <li>null, no assignment found</li>
|
||||
* </ol>
|
||||
*/
|
||||
public TargetAssignment getTargetAssignment( SourceMethod mappingMethod,
|
||||
public Assignment getTargetAssignment( SourceMethod mappingMethod,
|
||||
String mappedElement,
|
||||
List<MapperReference> mapperReferences,
|
||||
List<SourceMethod> methods,
|
||||
@ -174,52 +177,55 @@ public class MappingResolver {
|
||||
this.virtualMethodCandidates = new HashSet<VirtualMappingMethod>();
|
||||
}
|
||||
|
||||
private TargetAssignment getTargetAssignment( Type sourceType, Type targetType ) {
|
||||
private Assignment getTargetAssignment( Type sourceType, Type targetType ) {
|
||||
|
||||
// first simpele mapping method
|
||||
MethodReference mappingMethodReference = resolveViaMethod( sourceType, targetType );
|
||||
if ( mappingMethodReference != null ) {
|
||||
Assignment referencedMethod = resolveViaMethod( sourceType, targetType );
|
||||
if ( referencedMethod != null ) {
|
||||
referencedMethod.setAssignment( AssignmentFactory.createAssignment( sourceReference ) );
|
||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||
return new TargetAssignment( mappingMethodReference );
|
||||
return referencedMethod;
|
||||
}
|
||||
|
||||
// then direct assignable
|
||||
if ( sourceType.isAssignableTo( targetType ) ) {
|
||||
return new TargetAssignment();
|
||||
if ( sourceType.isAssignableTo( targetType ) || context.isPropertyMappable( sourceType, targetType ) ) {
|
||||
SimpleAssignment simpleAssignment = AssignmentFactory.createAssignment( sourceReference );
|
||||
return simpleAssignment;
|
||||
}
|
||||
|
||||
// then type conversion
|
||||
TypeConversion conversion = resolveViaConversion( sourceType, targetType );
|
||||
Assignment conversion = resolveViaConversion( sourceType, targetType );
|
||||
if ( conversion != null ) {
|
||||
return new TargetAssignment( conversion );
|
||||
conversion.setAssignment( AssignmentFactory.createAssignment( sourceReference) );
|
||||
return conversion;
|
||||
}
|
||||
|
||||
// 2 step method, first: method(method(souurce))
|
||||
mappingMethodReference = resolveViaMethodAndMethod( sourceType, targetType );
|
||||
if ( mappingMethodReference != null ) {
|
||||
referencedMethod = resolveViaMethodAndMethod( sourceType, targetType );
|
||||
if ( referencedMethod != null ) {
|
||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||
return new TargetAssignment( mappingMethodReference );
|
||||
return referencedMethod;
|
||||
}
|
||||
|
||||
// 2 step method, then: method(conversion(souurce))
|
||||
mappingMethodReference = resolveViaConversionAndMethod( sourceType, targetType );
|
||||
if ( mappingMethodReference != null ) {
|
||||
referencedMethod = resolveViaConversionAndMethod( sourceType, targetType );
|
||||
if ( referencedMethod != null ) {
|
||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||
return new TargetAssignment( mappingMethodReference );
|
||||
return referencedMethod;
|
||||
}
|
||||
|
||||
// 2 step method, finally: conversion(method(souurce))
|
||||
conversion = resolveViaMethodAndConversion( sourceType, targetType );
|
||||
if ( conversion != null ) {
|
||||
context.virtualMethods.addAll( virtualMethodCandidates );
|
||||
return new TargetAssignment( conversion );
|
||||
return conversion;
|
||||
}
|
||||
|
||||
// if nothing works, alas, the result is null
|
||||
return null;
|
||||
}
|
||||
|
||||
private TypeConversion resolveViaConversion( Type sourceType, Type targetType ) {
|
||||
private Assignment resolveViaConversion( Type sourceType, Type targetType ) {
|
||||
|
||||
ConversionProvider conversionProvider = context.conversions.getConversion( sourceType, targetType );
|
||||
|
||||
@ -227,10 +233,9 @@ public class MappingResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
return conversionProvider.to(
|
||||
sourceReference,
|
||||
new DefaultConversionContext( context.typeFactory, targetType, dateFormat )
|
||||
);
|
||||
ConversionContext ctx = new DefaultConversionContext( context.typeFactory, targetType, dateFormat );
|
||||
Assignment typeConversion = conversionProvider.to( ctx );
|
||||
return typeConversion;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,7 +243,7 @@ public class MappingResolver {
|
||||
* exists.
|
||||
*
|
||||
*/
|
||||
private MethodReference resolveViaMethod( Type sourceType, Type targetType ) {
|
||||
private Assignment resolveViaMethod( Type sourceType, Type targetType ) {
|
||||
|
||||
// first try to find a matching source method
|
||||
SourceMethod matchingSourceMethod = getBestMatch( methods, sourceType, targetType );
|
||||
@ -254,7 +259,9 @@ public class MappingResolver {
|
||||
if ( matchingBuiltInMethod != null ) {
|
||||
virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) );
|
||||
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;
|
||||
@ -270,12 +277,12 @@ public class MappingResolver {
|
||||
* </ul>
|
||||
* 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 );
|
||||
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.
|
||||
// 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(),
|
||||
targetType );
|
||||
if ( methodRefY != null ) {
|
||||
MethodReference methodRefX = resolveViaMethod(
|
||||
Assignment methodRefX = resolveViaMethod(
|
||||
sourceType,
|
||||
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
||||
);
|
||||
if ( methodRefX != null ) {
|
||||
methodRefY.setMethodRefChild( methodRefX );
|
||||
methodRefY.setAssignment( methodRefX );
|
||||
methodRefX.setAssignment( AssignmentFactory.createAssignment( sourceReference ) );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@ -315,12 +323,12 @@ public class MappingResolver {
|
||||
* </ul>
|
||||
* 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 );
|
||||
methodYCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
||||
|
||||
MethodReference methodRefY = null;
|
||||
Assignment methodRefY = null;
|
||||
|
||||
for ( Method methodYCandidate : methodYCandidates ) {
|
||||
if ( methodYCandidate.getSourceParameters().size() == 1 ) {
|
||||
@ -329,12 +337,13 @@ public class MappingResolver {
|
||||
targetType
|
||||
);
|
||||
if ( methodRefY != null ) {
|
||||
TypeConversion conversionXRef = resolveViaConversion(
|
||||
Assignment conversionXRef = resolveViaConversion(
|
||||
sourceType,
|
||||
methodYCandidate.getSourceParameters().get( 0 ).getType()
|
||||
);
|
||||
if ( conversionXRef != null ) {
|
||||
methodRefY.setTypeConversionChild( conversionXRef );
|
||||
methodRefY.setAssignment( conversionXRef );
|
||||
conversionXRef.setAssignment( new SimpleAssignment( sourceReference ) );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@ -356,27 +365,25 @@ public class MappingResolver {
|
||||
* </ul>
|
||||
* 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 );
|
||||
methodXCandidates.addAll( context.builtInMethods.getBuiltInMethods() );
|
||||
|
||||
TypeConversion conversionYRef = null;
|
||||
Assignment conversionYRef = null;
|
||||
|
||||
// search the other way arround
|
||||
for ( Method methodXCandidate : methodXCandidates ) {
|
||||
if ( methodXCandidate.getSourceParameters().size() == 1 ) {
|
||||
MethodReference methodRefX = resolveViaMethod(
|
||||
Assignment methodRefX = resolveViaMethod(
|
||||
sourceType,
|
||||
methodXCandidate.getReturnType()
|
||||
);
|
||||
if ( methodRefX != null ) {
|
||||
conversionYRef = resolveViaConversion(
|
||||
methodXCandidate.getReturnType(),
|
||||
targetType
|
||||
);
|
||||
conversionYRef = resolveViaConversion( methodXCandidate.getReturnType(), targetType );
|
||||
if ( conversionYRef != null ) {
|
||||
conversionYRef.setMethodRefChild( methodRefX );
|
||||
conversionYRef.setAssignment( methodRefX );
|
||||
methodRefX.setAssignment( new SimpleAssignment( sourceReference ) );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
@ -423,12 +430,12 @@ public class MappingResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
private MethodReference getMappingMethodReference( SourceMethod method,
|
||||
private Assignment getMappingMethodReference( SourceMethod method,
|
||||
List<MapperReference> mapperReferences,
|
||||
Type targetType ) {
|
||||
MapperReference mapperReference = findMapperReference( mapperReferences, method );
|
||||
|
||||
return new MethodReference(
|
||||
return AssignmentFactory.createAssignment(
|
||||
method,
|
||||
mapperReference,
|
||||
SourceMethod.containsTargetTypeParameter( method.getParameters() ) ? targetType : null
|
||||
@ -444,4 +451,113 @@ public class MappingResolver {
|
||||
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>
|
||||
|
||||
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">
|
||||
|
||||
|
@ -36,13 +36,11 @@
|
||||
<@includeModel object=keyAssignment
|
||||
target=keyVariableName
|
||||
targetType=typeName(resultType.typeParameters[0])
|
||||
source="entry.getKey()"
|
||||
isLocalVar=true/>
|
||||
<#-- value -->
|
||||
<@includeModel object=valueAssignment
|
||||
target=valueVariableName
|
||||
targetType=typeName(resultType.typeParameters[1])
|
||||
source="entry.getValue()"
|
||||
isLocalVar=true/>
|
||||
${resultName}.put( ${keyVariableName}, ${valueVariableName} );
|
||||
}
|
||||
|
@ -20,13 +20,7 @@
|
||||
-->
|
||||
<#if !( targetType.collectionType || targetType.mapType ) >
|
||||
<#-- non collections or maps -->
|
||||
<#if ( !sourceType.primitive && propertyAssignment.assignmentType!="ASSIGNMENT" ) >
|
||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
||||
<@assignmentLine/>
|
||||
}
|
||||
<#else>
|
||||
<@assignmentLine/>
|
||||
</#if>
|
||||
<@assignment aTargetType=targetType/>
|
||||
<#else>
|
||||
<#-- collections or maps -->
|
||||
<#if ( ext.existingInstanceMapping || !targetAccessorSetter ) >
|
||||
@ -34,39 +28,19 @@
|
||||
<#if ext.existingInstanceMapping>
|
||||
${ext.targetBeanName}.${targetReadAccessorName}().clear();
|
||||
</#if><#t>
|
||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
||||
<#if targetType.collectionType>
|
||||
<@collectionOrMapAssignmentLine target="${ext.targetBeanName}.${targetReadAccessorName}().addAll"/>
|
||||
<@assignment aTarget="${ext.targetBeanName}.${targetReadAccessorName}().addAll"/>
|
||||
<#else>
|
||||
<@collectionOrMapAssignmentLine target="${ext.targetBeanName}.${targetReadAccessorName}().putAll"/>
|
||||
<@assignment aTarget="${ext.targetBeanName}.${targetReadAccessorName}().putAll"/>
|
||||
</#if>
|
||||
}
|
||||
}
|
||||
<#if targetAccessorSetter>
|
||||
else if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
||||
<@collectionOrMapAssignmentLine/>
|
||||
}
|
||||
else <@assignment/>
|
||||
</#if>
|
||||
<#elseif targetAccessorSetter>
|
||||
if ( ${sourceBeanName}.${sourceAccessorName}() != null ) {
|
||||
<@collectionOrMapAssignmentLine/>
|
||||
}
|
||||
<@assignment/>
|
||||
</#if>
|
||||
</#if>
|
||||
<#macro collectionOrMapAssignmentLine
|
||||
target="${ext.targetBeanName}.${targetAccessorName}"
|
||||
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 assignment aTarget="${ext.targetBeanName}.${targetAccessorName}" aTargetType=targetType>
|
||||
<@includeModel object=propertyAssignment target=aTarget targetType=aTargetType raw=true/>
|
||||
</#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 -->
|
||||
${ext.targetType}.class
|
||||
<#else>
|
||||
<#if methodRefChild??>
|
||||
<#-- 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>
|
||||
<@includeModel object=assignment targetType=singleSourceParameterType raw=ext.raw/>
|
||||
</#if>
|
||||
<#if param_has_next>, </#if>
|
||||
</#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>
|
||||
</#macro>
|
||||
</@compress>
|
@ -18,10 +18,4 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<#if methodRefChild??>
|
||||
<#-- 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>
|
||||
${ext.target}( new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/></#if>( ${sourceReference} ) );
|
@ -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