Search in sources :

Example 1 with ReadAccessor

use of org.mapstruct.ap.internal.util.accessor.ReadAccessor in project mapstruct by mapstruct.

the class Filters method recordAccessorsIn.

public Map<String, ReadAccessor> recordAccessorsIn(Collection<Element> recordComponents) {
    if (RECORD_COMPONENT_ACCESSOR_METHOD == null) {
        return java.util.Collections.emptyMap();
    }
    try {
        Map<String, ReadAccessor> recordAccessors = new LinkedHashMap<>();
        for (Element recordComponent : recordComponents) {
            ExecutableElement recordExecutableElement = (ExecutableElement) RECORD_COMPONENT_ACCESSOR_METHOD.invoke(recordComponent);
            recordAccessors.put(recordComponent.getSimpleName().toString(), ReadAccessor.fromGetter(recordExecutableElement, getReturnType(recordExecutableElement)));
        }
        return recordAccessors;
    } catch (IllegalAccessException | InvocationTargetException e) {
        return java.util.Collections.emptyMap();
    }
}
Also used : ReadAccessor(org.mapstruct.ap.internal.util.accessor.ReadAccessor) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableElement(javax.lang.model.element.VariableElement) Element(javax.lang.model.element.Element) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) InvocationTargetException(java.lang.reflect.InvocationTargetException) LinkedHashMap(java.util.LinkedHashMap)

Example 2 with ReadAccessor

use of org.mapstruct.ap.internal.util.accessor.ReadAccessor in project mapstruct by mapstruct.

the class Type method getAlternativeTargetAccessors.

/**
 * Alternative accessors could be a getter for a collection. By means of the
 * {@link java.util.Collection#addAll(java.util.Collection) } this getter can still
 * be used as targetAccessor. JAXB XJC tool generates such constructs.
 *
 * This method can be extended when new cases come along.
 *
 * @return an unmodifiable list of alternative target accessors.
 */
private List<Accessor> getAlternativeTargetAccessors() {
    if (alternativeTargetAccessors != null) {
        return alternativeTargetAccessors;
    }
    if (isRecord()) {
        alternativeTargetAccessors = Collections.emptyList();
    }
    if (alternativeTargetAccessors == null) {
        List<Accessor> result = new ArrayList<>();
        List<Accessor> setterMethods = getSetters();
        List<Accessor> readAccessors = new ArrayList<>(getPropertyReadAccessors().values());
        // All the fields are also alternative accessors
        readAccessors.addAll(filters.fieldsIn(getAllFields(), FieldElementAccessor::new));
        // (assuming it is initialized)
        for (Accessor readAccessor : readAccessors) {
            if (isCollectionOrMapOrStream(readAccessor) && !correspondingSetterMethodExists(readAccessor, setterMethods)) {
                result.add(readAccessor);
            } else if (readAccessor.getAccessorType() == AccessorType.FIELD && !correspondingSetterMethodExists(readAccessor, setterMethods)) {
                result.add(readAccessor);
            }
        }
        alternativeTargetAccessors = Collections.unmodifiableList(result);
    }
    return alternativeTargetAccessors;
}
Also used : ArrayList(java.util.ArrayList) Accessor(org.mapstruct.ap.internal.util.accessor.Accessor) PresenceCheckAccessor(org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor) FieldElementAccessor(org.mapstruct.ap.internal.util.accessor.FieldElementAccessor) ReadAccessor(org.mapstruct.ap.internal.util.accessor.ReadAccessor) MapValueAccessor(org.mapstruct.ap.internal.util.accessor.MapValueAccessor)

Example 3 with ReadAccessor

use of org.mapstruct.ap.internal.util.accessor.ReadAccessor in project mapstruct by mapstruct.

the class Type method getPropertyReadAccessors.

/**
 * getPropertyReadAccessors
 *
 * @return an unmodifiable map of all read accessors (including 'is' for booleans), indexed by property name
 */
public Map<String, ReadAccessor> getPropertyReadAccessors() {
    if (readAccessors == null) {
        Map<String, ReadAccessor> modifiableGetters = new LinkedHashMap<>();
        Map<String, ReadAccessor> recordAccessors = filters.recordAccessorsIn(getRecordComponents());
        modifiableGetters.putAll(recordAccessors);
        List<ReadAccessor> getterList = filters.getterMethodsIn(getAllMethods());
        for (ReadAccessor getter : getterList) {
            String simpleName = getter.getSimpleName();
            if (recordAccessors.containsKey(simpleName)) {
                // but the property name is isActive, since it is a record
                continue;
            }
            String propertyName = getPropertyName(getter);
            if (recordAccessors.containsKey(propertyName)) {
                // If there is already a record accessor, the property needs to be ignored
                continue;
            }
            if (modifiableGetters.containsKey(propertyName)) {
                // getFoo(); The latter is preferred.
                if (!simpleName.startsWith("is")) {
                    modifiableGetters.put(propertyName, getter);
                }
            } else {
                modifiableGetters.put(propertyName, getter);
            }
        }
        List<ReadAccessor> fieldsList = filters.fieldsIn(getAllFields(), ReadAccessor::fromField);
        for (ReadAccessor field : fieldsList) {
            String propertyName = getPropertyName(field);
            // If there was no getter or is method for booleans, then resort to the field.
            // If a field was already added do not add it again.
            modifiableGetters.putIfAbsent(propertyName, field);
        }
        readAccessors = Collections.unmodifiableMap(modifiableGetters);
    }
    return readAccessors;
}
Also used : ReadAccessor(org.mapstruct.ap.internal.util.accessor.ReadAccessor) LinkedHashMap(java.util.LinkedHashMap)

Example 4 with ReadAccessor

use of org.mapstruct.ap.internal.util.accessor.ReadAccessor in project mapstruct by mapstruct.

the class SourceReference method push.

public List<SourceReference> push(TypeFactory typeFactory, FormattingMessager messager, Method method) {
    List<SourceReference> result = new ArrayList<>();
    PropertyEntry deepestProperty = getDeepestProperty();
    if (deepestProperty != null) {
        Type type = deepestProperty.getType();
        Map<String, ReadAccessor> newDeepestReadAccessors = type.getPropertyReadAccessors();
        String parameterName = getParameter().getName();
        String deepestPropertyFullName = deepestProperty.getFullName();
        for (Map.Entry<String, ReadAccessor> newDeepestReadAccessorEntry : newDeepestReadAccessors.entrySet()) {
            // Always include the parameter name in the new full name.
            // Otherwise multi source parameters might be reported incorrectly
            String newFullName = parameterName + "." + deepestPropertyFullName + "." + newDeepestReadAccessorEntry.getKey();
            SourceReference sourceReference = new BuilderFromMapping().sourceName(newFullName).method(method).messager(messager).typeFactory(typeFactory).build();
            result.add(sourceReference);
        }
    }
    return result;
}
Also used : Type(org.mapstruct.ap.internal.model.common.Type) DeclaredType(javax.lang.model.type.DeclaredType) PropertyEntry.forSourceReference(org.mapstruct.ap.internal.model.beanmapping.PropertyEntry.forSourceReference) ReadAccessor(org.mapstruct.ap.internal.util.accessor.ReadAccessor) ArrayList(java.util.ArrayList) Map(java.util.Map)

Example 5 with ReadAccessor

use of org.mapstruct.ap.internal.util.accessor.ReadAccessor in project mapstruct by mapstruct.

the class Type method getPropertyWriteAccessors.

/**
 * getPropertyWriteAccessors returns a map of the write accessors according to the CollectionMappingStrategy. These
 * accessors include:
 * <ul>
 * <li>setters, the obvious candidate :-), {@link #getSetters() }</li>
 * <li>readAccessors, for collections that do not have a setter, e.g. for JAXB generated collection attributes
 * {@link #getPropertyReadAccessors() }</li>
 * <li>adders, typically for from table generated entities, {@link #getAdders() }</li>
 * </ul>
 *
 * @param cmStrategy collection mapping strategy
 * @return an unmodifiable map of all write accessors indexed by property name
 */
public Map<String, Accessor> getPropertyWriteAccessors(CollectionMappingStrategyGem cmStrategy) {
    // collect all candidate target accessors
    List<Accessor> candidates = new ArrayList<>(getSetters());
    candidates.addAll(getAlternativeTargetAccessors());
    Map<String, Accessor> result = new LinkedHashMap<>();
    for (Accessor candidate : candidates) {
        String targetPropertyName = getPropertyName(candidate);
        Accessor readAccessor = getPropertyReadAccessors().get(targetPropertyName);
        Type preferredType = determinePreferredType(readAccessor);
        Type targetType = determineTargetType(candidate);
        // The following if block, checks if the target accessor should be overruled by an add method.
        if (cmStrategy == CollectionMappingStrategyGem.SETTER_PREFERRED || cmStrategy == CollectionMappingStrategyGem.ADDER_PREFERRED || cmStrategy == CollectionMappingStrategyGem.TARGET_IMMUTABLE) {
            // first check if there's a setter method.
            Accessor adderMethod = null;
            if (candidate.getAccessorType() == AccessorType.SETTER && // ok, the current accessor is a setter. So now the strategy determines what to use
            cmStrategy == CollectionMappingStrategyGem.ADDER_PREFERRED) {
                adderMethod = getAdderForType(targetType, targetPropertyName);
            } else if (candidate.getAccessorType() == AccessorType.GETTER) {
                // the current accessor is a getter (no setter available). But still, an add method is according
                // to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
                adderMethod = getAdderForType(targetType, targetPropertyName);
            }
            if (adderMethod != null) {
                // an adder has been found (according strategy) so overrule current choice.
                candidate = adderMethod;
            }
        } else if (candidate.getAccessorType() == AccessorType.FIELD && (Executables.isFinal(candidate) || result.containsKey(targetPropertyName))) {
            // if the candidate is a field and a mapping already exists, then use that one, skip it.
            continue;
        }
        Accessor previousCandidate = result.get(targetPropertyName);
        if (previousCandidate == null || preferredType == null || (targetType != null && typeUtils.isAssignable(preferredType.getTypeMirror(), targetType.getTypeMirror()))) {
            result.put(targetPropertyName, candidate);
        }
    }
    return result;
}
Also used : AccessorType(org.mapstruct.ap.internal.util.accessor.AccessorType) DeclaredType(javax.lang.model.type.DeclaredType) WildcardType(javax.lang.model.type.WildcardType) ArrayType(javax.lang.model.type.ArrayType) PrimitiveType(javax.lang.model.type.PrimitiveType) ArrayList(java.util.ArrayList) Accessor(org.mapstruct.ap.internal.util.accessor.Accessor) PresenceCheckAccessor(org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor) FieldElementAccessor(org.mapstruct.ap.internal.util.accessor.FieldElementAccessor) ReadAccessor(org.mapstruct.ap.internal.util.accessor.ReadAccessor) MapValueAccessor(org.mapstruct.ap.internal.util.accessor.MapValueAccessor) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

ReadAccessor (org.mapstruct.ap.internal.util.accessor.ReadAccessor)5 ArrayList (java.util.ArrayList)3 LinkedHashMap (java.util.LinkedHashMap)3 DeclaredType (javax.lang.model.type.DeclaredType)2 Accessor (org.mapstruct.ap.internal.util.accessor.Accessor)2 FieldElementAccessor (org.mapstruct.ap.internal.util.accessor.FieldElementAccessor)2 MapValueAccessor (org.mapstruct.ap.internal.util.accessor.MapValueAccessor)2 PresenceCheckAccessor (org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Map (java.util.Map)1 Element (javax.lang.model.element.Element)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 TypeElement (javax.lang.model.element.TypeElement)1 VariableElement (javax.lang.model.element.VariableElement)1 ArrayType (javax.lang.model.type.ArrayType)1 PrimitiveType (javax.lang.model.type.PrimitiveType)1 WildcardType (javax.lang.model.type.WildcardType)1 PropertyEntry.forSourceReference (org.mapstruct.ap.internal.model.beanmapping.PropertyEntry.forSourceReference)1 Type (org.mapstruct.ap.internal.model.common.Type)1 AccessorType (org.mapstruct.ap.internal.util.accessor.AccessorType)1