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;
}
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();
}
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;
}
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);
}
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;
}
Aggregations