Search in sources :

Example 11 with SourceMethod

use of org.mapstruct.ap.internal.model.source.SourceMethod in project mapstruct by mapstruct.

the class LifecycleCallbackFactory method getAllAvailableMethods.

private static List<SourceMethod> getAllAvailableMethods(Method method, List<SourceMethod> sourceModelMethods) {
    ParameterProvidedMethods contextProvidedMethods = method.getContextProvidedMethods();
    if (contextProvidedMethods.isEmpty()) {
        return sourceModelMethods;
    }
    List<SourceMethod> methodsProvidedByParams = contextProvidedMethods.getAllProvidedMethodsInParameterOrder(method.getContextParameters());
    List<SourceMethod> availableMethods = new ArrayList<SourceMethod>(methodsProvidedByParams.size() + sourceModelMethods.size());
    availableMethods.addAll(methodsProvidedByParams);
    availableMethods.addAll(sourceModelMethods);
    return availableMethods;
}
Also used : ParameterProvidedMethods(org.mapstruct.ap.internal.model.source.ParameterProvidedMethods) ArrayList(java.util.ArrayList) SourceMethod(org.mapstruct.ap.internal.model.source.SourceMethod)

Example 12 with SourceMethod

use of org.mapstruct.ap.internal.model.source.SourceMethod in project mapstruct by mapstruct.

the class MapperCreationProcessor method mergeInheritedOptions.

private void mergeInheritedOptions(SourceMethod method, MapperConfiguration mapperConfig, List<SourceMethod> availableMethods, List<SourceMethod> initializingMethods) {
    if (initializingMethods.contains(method)) {
        // cycle detected
        initializingMethods.add(method);
        messager.printMessage(method.getExecutable(), Message.INHERITCONFIGURATION_CYCLE, Strings.join(initializingMethods, " -> "));
        return;
    }
    initializingMethods.add(method);
    MappingOptions mappingOptions = method.getMappingOptions();
    List<SourceMethod> applicableReversePrototypeMethods = method.getApplicableReversePrototypeMethods();
    MappingOptions inverseMappingOptions = getInverseMappingOptions(join(availableMethods, applicableReversePrototypeMethods), method, initializingMethods, mapperConfig);
    List<SourceMethod> applicablePrototypeMethods = method.getApplicablePrototypeMethods();
    MappingOptions forwardMappingOptions = getTemplateMappingOptions(join(availableMethods, applicablePrototypeMethods), method, initializingMethods, mapperConfig);
    // apply defined (@InheritConfiguration, @InheritInverseConfiguration) mappings
    if (forwardMappingOptions != null) {
        mappingOptions.applyInheritedOptions(forwardMappingOptions, false, method, messager, typeFactory);
    }
    if (inverseMappingOptions != null) {
        mappingOptions.applyInheritedOptions(inverseMappingOptions, true, method, messager, typeFactory);
    }
    // apply auto inherited options
    MappingInheritanceStrategyPrism inheritanceStrategy = mapperConfig.getMappingInheritanceStrategy();
    if (inheritanceStrategy.isAutoInherit()) {
        // but.. there should not be an @InheritedConfiguration
        if (forwardMappingOptions == null && inheritanceStrategy.isApplyForward()) {
            if (applicablePrototypeMethods.size() == 1) {
                mappingOptions.applyInheritedOptions(first(applicablePrototypeMethods).getMappingOptions(), false, method, messager, typeFactory);
            } else if (applicablePrototypeMethods.size() > 1) {
                messager.printMessage(method.getExecutable(), Message.INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH, Strings.join(applicablePrototypeMethods, ", "));
            }
        }
        // or no @InheritInverseConfiguration
        if (inverseMappingOptions == null && inheritanceStrategy.isApplyReverse()) {
            if (applicableReversePrototypeMethods.size() == 1) {
                mappingOptions.applyInheritedOptions(first(applicableReversePrototypeMethods).getMappingOptions(), true, method, messager, typeFactory);
            } else if (applicableReversePrototypeMethods.size() > 1) {
                messager.printMessage(method.getExecutable(), Message.INHERITINVERSECONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH, Strings.join(applicableReversePrototypeMethods, ", "));
            }
        }
    }
    mappingOptions.markAsFullyInitialized();
}
Also used : MappingOptions(org.mapstruct.ap.internal.model.source.MappingOptions) MappingInheritanceStrategyPrism(org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism) SourceMethod(org.mapstruct.ap.internal.model.source.SourceMethod)

Example 13 with SourceMethod

use of org.mapstruct.ap.internal.model.source.SourceMethod in project mapstruct by mapstruct.

the class MapperCreationProcessor method getDecorator.

private Decorator getDecorator(TypeElement element, List<SourceMethod> methods, String implName, String implPackage) {
    DecoratedWithPrism decoratorPrism = DecoratedWithPrism.getInstanceOn(element);
    if (decoratorPrism == null) {
        return null;
    }
    TypeElement decoratorElement = (TypeElement) typeUtils.asElement(decoratorPrism.value());
    if (!typeUtils.isAssignable(decoratorElement.asType(), element.asType())) {
        messager.printMessage(element, decoratorPrism.mirror, Message.DECORATOR_NO_SUBTYPE);
    }
    List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>(methods.size());
    for (SourceMethod mappingMethod : methods) {
        boolean implementationRequired = true;
        for (ExecutableElement method : ElementFilter.methodsIn(decoratorElement.getEnclosedElements())) {
            if (elementUtils.overrides(method, mappingMethod.getExecutable(), decoratorElement)) {
                implementationRequired = false;
                break;
            }
        }
        Type declaringMapper = mappingMethod.getDeclaringMapper();
        if (implementationRequired && !(mappingMethod.isDefault() || mappingMethod.isStatic())) {
            if ((declaringMapper == null) || declaringMapper.equals(typeFactory.getType(element))) {
                mappingMethods.add(new DelegatingMethod(mappingMethod));
            }
        }
    }
    boolean hasDelegateConstructor = false;
    boolean hasDefaultConstructor = false;
    for (ExecutableElement constructor : ElementFilter.constructorsIn(decoratorElement.getEnclosedElements())) {
        if (constructor.getParameters().isEmpty()) {
            hasDefaultConstructor = true;
        } else if (constructor.getParameters().size() == 1) {
            if (typeUtils.isAssignable(element.asType(), first(constructor.getParameters()).asType())) {
                hasDelegateConstructor = true;
            }
        }
    }
    if (!hasDelegateConstructor && !hasDefaultConstructor) {
        messager.printMessage(element, decoratorPrism.mirror, Message.DECORATOR_CONSTRUCTOR);
    }
    Decorator decorator = new Decorator.Builder().elementUtils(elementUtils).typeFactory(typeFactory).mapperElement(element).decoratorPrism(decoratorPrism).methods(mappingMethods).hasDelegateConstructor(hasDelegateConstructor).options(options).versionInformation(versionInformation).implName(implName).implPackage(implPackage).extraImports(getExtraImports(element)).build();
    return decorator;
}
Also used : Decorator(org.mapstruct.ap.internal.model.Decorator) Type(org.mapstruct.ap.internal.model.common.Type) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ContainerMappingMethodBuilder(org.mapstruct.ap.internal.model.ContainerMappingMethodBuilder) MapMappingMethod(org.mapstruct.ap.internal.model.MapMappingMethod) EnumMappingMethod(org.mapstruct.ap.internal.model.EnumMappingMethod) IterableMappingMethod(org.mapstruct.ap.internal.model.IterableMappingMethod) ValueMappingMethod(org.mapstruct.ap.internal.model.ValueMappingMethod) MappingMethod(org.mapstruct.ap.internal.model.MappingMethod) StreamMappingMethod(org.mapstruct.ap.internal.model.StreamMappingMethod) ContainerMappingMethod(org.mapstruct.ap.internal.model.ContainerMappingMethod) BeanMappingMethod(org.mapstruct.ap.internal.model.BeanMappingMethod) ArrayList(java.util.ArrayList) DelegatingMethod(org.mapstruct.ap.internal.model.DelegatingMethod) DecoratedWithPrism(org.mapstruct.ap.internal.prism.DecoratedWithPrism) SourceMethod(org.mapstruct.ap.internal.model.source.SourceMethod)

Example 14 with SourceMethod

use of org.mapstruct.ap.internal.model.source.SourceMethod in project mapstruct by mapstruct.

the class MapperCreationProcessor method getInverseMappingOptions.

/**
 * Returns the configuring inverse method's options in case the given method is annotated with
 * {@code @InheritInverseConfiguration} and exactly one such configuring method can unambiguously be selected (as
 * per the source/target type and optionally the name given via {@code @InheritInverseConfiguration}).
 */
private MappingOptions getInverseMappingOptions(List<SourceMethod> rawMethods, SourceMethod method, List<SourceMethod> initializingMethods, MapperConfiguration mapperConfig) {
    SourceMethod resultMethod = null;
    InheritInverseConfigurationPrism reversePrism = InheritInverseConfigurationPrism.getInstanceOn(method.getExecutable());
    if (reversePrism != null) {
        // method is configured as being reverse method, collect candidates
        List<SourceMethod> candidates = new ArrayList<SourceMethod>();
        for (SourceMethod oneMethod : rawMethods) {
            if (method.reverses(oneMethod)) {
                candidates.add(oneMethod);
            }
        }
        String name = reversePrism.name();
        if (candidates.size() == 1) {
            // no ambiguity: if no configuredBy is specified, or configuredBy specified and match
            if (name.isEmpty()) {
                resultMethod = candidates.get(0);
            } else if (candidates.get(0).getName().equals(name)) {
                resultMethod = candidates.get(0);
            } else {
                reportErrorWhenNonMatchingName(candidates.get(0), method, reversePrism);
            }
        } else if (candidates.size() > 1) {
            // ambiguity: find a matching method that matches configuredBy
            List<SourceMethod> nameFilteredcandidates = new ArrayList<SourceMethod>();
            for (SourceMethod candidate : candidates) {
                if (candidate.getName().equals(name)) {
                    nameFilteredcandidates.add(candidate);
                }
            }
            if (nameFilteredcandidates.size() == 1) {
                resultMethod = nameFilteredcandidates.get(0);
            } else if (nameFilteredcandidates.size() > 1) {
                reportErrorWhenSeveralNamesMatch(nameFilteredcandidates, method, reversePrism);
            } else {
                reportErrorWhenAmbigousReverseMapping(candidates, method, reversePrism);
            }
        }
    }
    return extractInitializedOptions(resultMethod, rawMethods, mapperConfig, initializingMethods);
}
Also used : ArrayList(java.util.ArrayList) InheritInverseConfigurationPrism(org.mapstruct.ap.internal.prism.InheritInverseConfigurationPrism) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) SourceMethod(org.mapstruct.ap.internal.model.source.SourceMethod)

Example 15 with SourceMethod

use of org.mapstruct.ap.internal.model.source.SourceMethod in project mapstruct by mapstruct.

the class MethodRetrievalProcessor method retrievePrototypeMethods.

private List<SourceMethod> retrievePrototypeMethods(TypeElement mapperTypeElement, MapperConfiguration mapperConfig) {
    if (mapperConfig.config() == null) {
        return Collections.emptyList();
    }
    TypeElement typeElement = asTypeElement(mapperConfig.config());
    List<SourceMethod> methods = new ArrayList<SourceMethod>();
    for (ExecutableElement executable : getAllEnclosedExecutableElements(elementUtils, typeElement)) {
        ExecutableType methodType = typeFactory.getMethodType(mapperConfig.config(), executable);
        List<Parameter> parameters = typeFactory.getParameters(methodType, executable);
        boolean containsTargetTypeParameter = SourceMethod.containsTargetTypeParameter(parameters);
        // prototype methods don't have prototypes themselves
        List<SourceMethod> prototypeMethods = Collections.emptyList();
        SourceMethod method = getMethodRequiringImplementation(methodType, executable, parameters, containsTargetTypeParameter, mapperConfig, prototypeMethods, mapperTypeElement);
        if (method != null) {
            methods.add(method);
        }
    }
    return methods;
}
Also used : ExecutableType(javax.lang.model.type.ExecutableType) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) Parameter(org.mapstruct.ap.internal.model.common.Parameter) SourceMethod(org.mapstruct.ap.internal.model.source.SourceMethod)

Aggregations

SourceMethod (org.mapstruct.ap.internal.model.source.SourceMethod)16 ArrayList (java.util.ArrayList)12 DeclaredType (javax.lang.model.type.DeclaredType)3 Parameter (org.mapstruct.ap.internal.model.common.Parameter)3 Type (org.mapstruct.ap.internal.model.common.Type)3 LinkedList (java.util.LinkedList)2 List (java.util.List)2 AnnotationMirror (javax.lang.model.element.AnnotationMirror)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 TypeElement (javax.lang.model.element.TypeElement)2 ExecutableType (javax.lang.model.type.ExecutableType)2 TypeMirror (javax.lang.model.type.TypeMirror)2 BeanMappingMethod (org.mapstruct.ap.internal.model.BeanMappingMethod)2 ContainerMappingMethod (org.mapstruct.ap.internal.model.ContainerMappingMethod)2 ContainerMappingMethodBuilder (org.mapstruct.ap.internal.model.ContainerMappingMethodBuilder)2 EnumMappingMethod (org.mapstruct.ap.internal.model.EnumMappingMethod)2 IterableMappingMethod (org.mapstruct.ap.internal.model.IterableMappingMethod)2 MapMappingMethod (org.mapstruct.ap.internal.model.MapMappingMethod)2 MappingMethod (org.mapstruct.ap.internal.model.MappingMethod)2 StreamMappingMethod (org.mapstruct.ap.internal.model.StreamMappingMethod)2