@Override public void encountered(Class<?> proxyType, Method method, Object[] args) { if (PropertyResolver.MUTATORS.isValid(method)) { String propertyName = config.getDestinationNameTransformer().transform(method.getName(), NameableType.METHOD); propertyInfo.add(PropertyInfoRegistry.mutatorFor(proxyType, method, config, propertyName)); argument = args.length == 1 ? args[0] : null; if (argument != null && argument == builder.source) builder.errors.missingSource(); builder.saveMapping(); } else if (PropertyResolver.ACCESSORS.isValid(method)) { // Find mutator corresponding to accessor Mutator mutator = TypeInfoRegistry.typeInfoFor(proxyType, config) .mutatorForAccessorMethod(method.getName()); if (mutator != null) propertyInfo.add(mutator); else builder.errors.missingMutatorForAccessor(method); } else builder.errors.invalidDestinationMethod(method); }
/** * Sets a mapped or converted destination value in the last mapped mutator for the given {@code * mapping}. The final destination value is resolved by walking the {@code mapping}'s mutator * chain and obtaining each destination value in the chain either from the cache, from a * corresponding accessor, from a provider, or by instantiation, in that order. */ @SuppressWarnings({"unchecked", "rawtypes"}) private void setDestinationValue( MappingContextImpl<?, ?> context, MappingContextImpl<Object, Object> propertyContext, MappingImpl mapping, Converter<Object, Object> converter) { Object destination = context.getDestination(); List<Mutator> mutatorChain = (List<Mutator>) mapping.getDestinationProperties(); StringBuilder destPathBuilder = new StringBuilder(); for (int i = 0; i < mutatorChain.size(); i++) { Mutator mutator = mutatorChain.get(i); destPathBuilder.append(mutator.getName()).append('.'); String destPath = destPathBuilder.toString(); // Handle last mutator in chain if (i == mutatorChain.size() - 1) { // Final destination value Object destinationValue = null; if (converter != null) { // Obtain from accessor on provided destination if (context.providedDestination) { Accessor accessor = TypeInfoRegistry.typeInfoFor(destination.getClass(), configuration) .getAccessors() .get(mutator.getName()); if (accessor != null) { Object intermediateDest = accessor.getValue(destination); propertyContext.setDestination(intermediateDest); } } destinationValue = convert(propertyContext, converter); } else if (propertyContext.getSource() != null) destinationValue = map(propertyContext); context.destinationCache.put(destPath, destinationValue); mutator.setValue( destination, destinationValue == null ? Primitives.defaultValue(mutator.getType()) : destinationValue); if (destinationValue == null) context.shadePath(mapping.getPath()); } else { // Obtain from cache Object intermediateDest = context.destinationCache.get(destPath); if (intermediateDest != null) { mutator.setValue(destination, intermediateDest); } else { // Obtain from circular destinations if (!context.intermediateDestinations.isEmpty()) { for (Object intermediateDestination : context.intermediateDestinations) { // Match intermediate destinations to mutator by type if (intermediateDestination.getClass().equals(mutator.getType())) { intermediateDest = intermediateDestination; mutator.setValue(destination, intermediateDest); break; } } } if (intermediateDest == null) { // Obtain from accessor on provided destination if (context.providedDestination) { Accessor accessor = TypeInfoRegistry.typeInfoFor(destination.getClass(), configuration) .getAccessors() .get(mutator.getName()); if (accessor != null) intermediateDest = accessor.getValue(destination); } // Obtain from new instance if (intermediateDest == null) { if (propertyContext.getSource() == null) return; Provider<?> globalProvider = configuration.getProvider(); if (globalProvider != null) intermediateDest = globalProvider.get( new ProvisionRequestImpl(context.parentSource(), mutator.getType())); else intermediateDest = instantiate(mutator.getType(), context.errors); if (intermediateDest == null) return; mutator.setValue(destination, intermediateDest); } } context.destinationCache.put(destPath, intermediateDest); } destination = intermediateDest; } } }