
org.mapstruct.ap.internal.model.MethodReference Maven / Gradle / Ivy
/**
* Copyright 2012-2017 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.internal.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mapstruct.ap.internal.model.common.Assignment;
import org.mapstruct.ap.internal.model.common.ConversionContext;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod;
/**
* Represents a reference to another method, e.g. used to map a bean property from source to target type or to
* instantiate the return value of a mapping method (rather than calling the {@code new} operator).
*
* @author Gunnar Morling
*/
public class MethodReference extends MappingMethod implements Assignment {
private final MapperReference declaringMapper;
private final Set importTypes;
private final List thrownTypes;
private final boolean isUpdateMethod;
/**
* 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
* which requires that.
*/
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} to {@code Foo} to for which a nested method call will be generated:
* {@code setFoo(barToFoo( jaxbElemToValue( bar) ) )}. If there's no nested typeConversion or other mapping method,
* this will be a direct assignment.
*/
private Assignment assignment;
private final Type definingType;
private final List parameterBindings;
private final Parameter providingParameter;
/**
* Creates a new reference to the given method.
*
* @param method the target method of the reference
* @param declaringMapper the method declaring the mapper; {@code null} if the current mapper itself
* @param providingParameter The parameter providing the mapper, or {@code null} if the method is defined by the
* mapper itself or by {@code declaringMapper}.
* @param parameterBindings the parameter bindings of this method reference
*/
protected MethodReference(Method method, MapperReference declaringMapper, Parameter providingParameter,
List parameterBindings) {
super( method );
this.declaringMapper = declaringMapper;
this.providingParameter = providingParameter;
this.parameterBindings = parameterBindings;
this.contextParam = null;
Set imported = new HashSet();
for ( Type type : method.getThrownTypes() ) {
imported.addAll( type.getImportTypes() );
}
for ( ParameterBinding binding : parameterBindings ) {
imported.addAll( binding.getImportTypes() );
}
this.importTypes = Collections.unmodifiableSet( imported );
this.thrownTypes = method.getThrownTypes();
this.isUpdateMethod = method.getMappingTargetParameter() != null;
this.definingType = method.getDefiningType();
}
private MethodReference(BuiltInMethod method, ConversionContext contextParam) {
super( method );
this.declaringMapper = null;
this.providingParameter = null;
this.contextParam = method.getContextParameter( contextParam );
this.importTypes = Collections.emptySet();
this.thrownTypes = Collections.emptyList();
this.definingType = null;
this.isUpdateMethod = method.getMappingTargetParameter() != null;
this.parameterBindings = ParameterBinding.fromParameters( method.getParameters() );
}
public MapperReference getDeclaringMapper() {
return declaringMapper;
}
public Parameter getProvidingParameter() {
return providingParameter;
}
public String getMapperVariableName() {
return declaringMapper.getVariableName();
}
public String getContextParam() {
return contextParam;
}
public Assignment getAssignment() {
return assignment;
}
@Override
public void setAssignment( Assignment assignment ) {
this.assignment = assignment;
}
@Override
public String getSourceReference() {
return assignment.getSourceReference();
}
@Override
public String getSourcePresenceCheckerReference() {
return assignment.getSourcePresenceCheckerReference();
}
@Override
public Type getSourceType() {
return assignment.getSourceType();
}
@Override
public String createLocalVarName( String desiredName ) {
return assignment.createLocalVarName( desiredName );
}
@Override
public String getSourceLocalVarName() {
return assignment.getSourceLocalVarName();
}
@Override
public void setSourceLocalVarName(String sourceLocalVarName) {
assignment.setSourceLocalVarName( sourceLocalVarName );
}
@Override
public String getSourceParameterName() {
return assignment.getSourceParameterName();
}
@Override
public boolean isSourceReferenceParameter() {
return assignment.isSourceReferenceParameter();
}
/**
* @return the type of the single source parameter that is not the {@code @TargetType} parameter
*/
public Type getSingleSourceParameterType() {
for ( Parameter parameter : getSourceParameters() ) {
if ( !parameter.isTargetType() ) {
return parameter.getType();
}
}
return null;
}
public Type getDefiningType() {
return definingType;
}
@Override
public Set getImportTypes() {
Set imported = new HashSet( importTypes );
if ( assignment != null ) {
imported.addAll( assignment.getImportTypes() );
}
if ( isStatic() ) {
imported.add( definingType );
}
return imported;
}
@Override
public List getThrownTypes() {
List exceptions = new ArrayList();
exceptions.addAll( thrownTypes );
if ( assignment != null ) {
exceptions.addAll( assignment.getThrownTypes() );
}
return exceptions;
}
@Override
public AssignmentType getType() {
switch ( assignment.getType() ) {
case DIRECT:
return AssignmentType.MAPPED;
case MAPPED:
return AssignmentType.MAPPED_TWICE;
case TYPE_CONVERTED:
return AssignmentType.TYPE_CONVERTED_MAPPED;
default:
return null;
}
}
@Override
public boolean isCallingUpdateMethod() {
return isUpdateMethod;
}
public List getParameterBindings() {
return parameterBindings;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ( ( declaringMapper == null ) ? 0 : declaringMapper.hashCode() );
result = prime * result + ( ( providingParameter == null ) ? 0 : providingParameter.hashCode() );
return result;
}
@Override
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
if ( !super.equals( obj ) ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
MethodReference other = (MethodReference) obj;
if ( declaringMapper == null ) {
if ( other.declaringMapper != null ) {
return false;
}
}
else if ( !declaringMapper.equals( other.declaringMapper ) ) {
return false;
}
if ( providingParameter == null ) {
if ( other.providingParameter != null ) {
return false;
}
}
else if ( !providingParameter.equals( other.providingParameter ) ) {
return false;
}
return true;
}
public static MethodReference forBuiltInMethod(BuiltInMethod method, ConversionContext contextParam) {
return new MethodReference( method, contextParam );
}
public static MethodReference forForgedMethod(Method method, List parameterBindings) {
return new MethodReference( method, null, null, parameterBindings );
}
public static MethodReference forParameterProvidedMethod(Method method, Parameter providingParameter,
List parameterBindings) {
return new MethodReference( method, null, providingParameter, parameterBindings );
}
public static MethodReference forMapperReference(Method method, MapperReference declaringMapper,
List parameterBindings) {
return new MethodReference( method, declaringMapper, null, parameterBindings );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy