/** * 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.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import org.mapstruct.ap.internal.model.assignment.Assignment; import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.common.FormattingParameters; import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SourceMethod; import org.mapstruct.ap.internal.option.Options; import org.mapstruct.ap.internal.util.FormattingMessager; /** * This class provides the context for the builders. * <p> * The context provides: * <ul> * <li>Input for the building process, such as the source model (mapping methods found) and mapper references.</li> * <li>Required factory, utility, reporting methods for building the mappings.</li> * <li>Means to harbor results produced by the builders, such as forged- and virtual mapping methods that should be * generated in a later stage.</li> * </ul> * * @author Sjaak Derksen */ public class MappingBuilderContext { /** * Resolves the most suitable way for mapping an element (property, iterable element etc.) from source to target. * There are 2 basic types of mappings: * <ul> * <li>conversions</li> * <li>methods</li> * </ul> * conversions are essentially one line mappings, such as String to Integer and Integer to Long methods come in some * varieties: * <ul> * <li>referenced mapping methods, these are methods implemented (or referenced) by the user. Sometimes indicated * with the 'uses' in the mapping annotations or part of the abstract mapper class</li> * <li>generated mapping methods (by means of MapStruct)</li> * <li>built in methods</li> * </ul> * * @author Sjaak Derksen */ public interface MappingResolver { /** * returns a parameter assignment * * @param mappingMethod target mapping method * @param targetType return type to match * @param targetPropertyName name of the target property * @param formattingParameters used for formatting dates and numbers * @param selectionParameters parameters used in the selection process * @param sourceRHS source information * @param preferUpdateMethods selection should prefer update methods when present. * * @return an assignment to a method parameter, which can either be: * <ol> * <li>MethodReference</li> * <li>TypeConversion</li> * <li>SourceRHS Assignment (empty TargetAssignment)</li> * <li>null, no assignment found</li> * </ol> */ Assignment getTargetAssignment(Method mappingMethod, Type targetType, String targetPropertyName, FormattingParameters formattingParameters, SelectionParameters selectionParameters, SourceRHS sourceRHS, boolean preferUpdateMethods); /** * returns a no arg factory method * * @param mappingMethod target mapping method * @param target return type to match * @param selectionParameters parameters used in the selection process * * @return a method reference to the factory method, or null if no suitable, or ambiguous method found * */ MethodReference getFactoryMethod(Method mappingMethod, Type target, SelectionParameters selectionParameters); Set<VirtualMappingMethod> getUsedVirtualMappings(); } private final TypeFactory typeFactory; private final Elements elementUtils; private final Types typeUtils; private final FormattingMessager messager; private final Options options; private final TypeElement mapperTypeElement; private final List<SourceMethod> sourceModel; private final List<MapperReference> mapperReferences; private final MappingResolver mappingResolver; private final List<MappingMethod> mappingsToGenerate = new ArrayList<MappingMethod>(); private final Map<ForgedMethod, ForgedMethod> forgedMethodsUnderCreation = new HashMap<ForgedMethod, ForgedMethod>( ); public MappingBuilderContext(TypeFactory typeFactory, Elements elementUtils, Types typeUtils, FormattingMessager messager, Options options, MappingResolver mappingResolver, TypeElement mapper, List<SourceMethod> sourceModel, List<MapperReference> mapperReferences) { this.typeFactory = typeFactory; this.elementUtils = elementUtils; this.typeUtils = typeUtils; this.messager = messager; this.options = options; this.mappingResolver = mappingResolver; this.mapperTypeElement = mapper; this.sourceModel = sourceModel; this.mapperReferences = mapperReferences; } /** * Returns a map which is used to track which forged methods are under creation. * Used for cutting the possible infinite recursion of forged method creation. * * Map is used instead of set because not all fields of ForgedMethods are used in equals/hashCode and we are * interested only in the first created ForgedMethod * * @return map of forged methods */ public Map<ForgedMethod, ForgedMethod> getForgedMethodsUnderCreation() { return forgedMethodsUnderCreation; } public TypeElement getMapperTypeElement() { return mapperTypeElement; } public List<SourceMethod> getSourceModel() { return sourceModel; } public List<MapperReference> getMapperReferences() { return mapperReferences; } public TypeFactory getTypeFactory() { return typeFactory; } public Elements getElementUtils() { return elementUtils; } public Types getTypeUtils() { return typeUtils; } public FormattingMessager getMessager() { return messager; } public Options getOptions() { return options; } public MappingResolver getMappingResolver() { return mappingResolver; } public List<MappingMethod> getMappingsToGenerate() { return mappingsToGenerate; } public List<String> getNamesOfMappingsToGenerate() { List<String> nameList = new ArrayList<String>(); for ( MappingMethod method : mappingsToGenerate ) { nameList.add( method.getName() ); } return nameList; } public MappingMethod getExistingMappingMethod(MappingMethod newMappingMethod) { MappingMethod existingMappingMethod = null; for ( MappingMethod mappingMethod : mappingsToGenerate ) { if ( newMappingMethod.equals( mappingMethod ) ) { existingMappingMethod = mappingMethod; break; } } return existingMappingMethod; } public Set<VirtualMappingMethod> getUsedVirtualMappings() { return mappingResolver.getUsedVirtualMappings(); } }