<commit_before>/*
 * Copyright 2014 - 2021 Blazebit.
 *
 * 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 com.blazebit.persistence.view.impl.metamodel;

import com.blazebit.persistence.spi.AttributePath;
import com.blazebit.persistence.view.AttributeFilterProvider;
import com.blazebit.persistence.view.CascadeType;
import com.blazebit.persistence.view.InverseRemoveStrategy;
import com.blazebit.persistence.view.Mapping;
import com.blazebit.persistence.view.MappingCorrelated;
import com.blazebit.persistence.view.MappingCorrelatedSimple;
import com.blazebit.persistence.view.MappingIndex;
import com.blazebit.persistence.view.MappingParameter;
import com.blazebit.persistence.view.MappingSubquery;
import com.blazebit.persistence.view.impl.ReflectionUtils;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodCollectionAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMultiListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMultiMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodSetAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodSingularAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodCollectionAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMultiListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMultiMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodSetAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodSingularAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.SubqueryMethodSingularAttribute;
import com.blazebit.persistence.view.metamodel.PluralAttribute;
import com.blazebit.persistence.view.spi.EntityViewMethodAttributeMapping;

import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Type;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author <NAME>
 * @since 1.2.0
 */
public class MethodAttributeMapping extends AttributeMapping implements EntityViewMethodAttributeMapping {

    private final String attributeName;
    private final Method method;
    private final Method setterMethod;
    private final int attributeIndex;

    private Map<String, Class<? extends AttributeFilterProvider<?>>> attributeFilterProviders;

    // Updatable configs
    private Boolean isUpdatable;
    private Boolean isOrphanRemoval;
    private Boolean isOptimisticLockProtected;
    private String mappedBy;
    private Map<EmbeddableOwner, String> embeddableMappedByMap;
    private InverseRemoveStrategy inverseRemoveStrategy;
    private Set<CascadeType> cascadeTypes = Collections.singleton(CascadeType.AUTO);
    private Set<Class<?>> cascadeSubtypeClasses;
    private Set<Class<?>> cascadePersistSubtypeClasses;
    private Set<Class<?>> cascadeUpdateSubtypeClasses;

    private Map<ViewMapping, Boolean> readOnlySubtypeMappings;
    private Map<ViewMapping, Boolean> cascadeSubtypeMappings;
    private Map<ViewMapping, Boolean> cascadePersistSubtypeMappings;
    private Map<ViewMapping, Boolean> cascadeUpdateSubtypeMappings;
    private Set<ManagedViewTypeImplementor<?>> readOnlySubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadeSubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadePersistSubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadeUpdateSubtypes;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableReadOnlySubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadeSubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadePersistSubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadeUpdateSubtypesMap;

    public MethodAttributeMapping(ViewMapping viewMapping, Annotation mapping, MappingIndex mappingIndex, MetamodelBootContext context, String attributeName, Method method, int attributeIndex, boolean isCollection, PluralAttribute.ElementCollectionType elementCollectionType, Class<?> declaredTypeClass, Class<?> declaredKeyTypeClass, Class declaredElementTypeClass,
                                  java.lang.reflect.Type type, java.lang.reflect.Type keyType, java.lang.reflect.Type elementType, Map<Class<?>, String> inheritanceSubtypeClassMappings, Map<Class<?>, String> keyInheritanceSubtypeClassMappings, Map<Class<?>, String> elementInheritanceSubtypeClassMappings) {
        super(viewMapping, mapping, mappingIndex, context, isCollection, elementCollectionType, declaredTypeClass, declaredKeyTypeClass, declaredElementTypeClass, type, keyType, elementType, inheritanceSubtypeClassMappings, keyInheritanceSubtypeClassMappings, elementInheritanceSubtypeClassMappings);
        this.attributeName = attributeName;
        this.method = method;
        this.attributeIndex = attributeIndex;
        Method setter = null;
        List<Method> setters = ReflectionUtils.getSetters(viewMapping.getEntityViewClass(), attributeName);
        List<Method> illegalSetters = null;
        for (Method m : setters) {
            if ((m.getModifiers() & Modifier.ABSTRACT) != 0) {
                if (com.blazebit.reflection.ReflectionUtils.getResolvedMethodParameterTypes(viewMapping.getEntityViewClass(), m)[0].equals(com.blazebit.reflection.ReflectionUtils.getResolvedMethodReturnType(viewMapping.getEntityViewClass(), method))) {
                    setter = m;
                    break;
                } else {
                    if (illegalSetters == null) {
                        illegalSetters = new ArrayList<>();<commit_msg>[#1368] Fix setter determination in entity views to respect covariant overridden getters<commit_after>/*
 * Copyright 2014 - 2021 Blazebit.
 *
 * 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 com.blazebit.persistence.view.impl.metamodel;

import com.blazebit.persistence.spi.AttributePath;
import com.blazebit.persistence.view.AttributeFilterProvider;
import com.blazebit.persistence.view.CascadeType;
import com.blazebit.persistence.view.InverseRemoveStrategy;
import com.blazebit.persistence.view.Mapping;
import com.blazebit.persistence.view.MappingCorrelated;
import com.blazebit.persistence.view.MappingCorrelatedSimple;
import com.blazebit.persistence.view.MappingIndex;
import com.blazebit.persistence.view.MappingParameter;
import com.blazebit.persistence.view.MappingSubquery;
import com.blazebit.persistence.view.impl.ReflectionUtils;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodCollectionAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMultiListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodMultiMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodSetAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.CorrelatedMethodSingularAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodCollectionAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMultiListAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodMultiMapAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodSetAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.MappingMethodSingularAttribute;
import com.blazebit.persistence.view.impl.metamodel.attribute.SubqueryMethodSingularAttribute;
import com.blazebit.persistence.view.metamodel.PluralAttribute;
import com.blazebit.persistence.view.spi.EntityViewMethodAttributeMapping;

import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Type;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author <NAME>
 * @since 1.2.0
 */
public class MethodAttributeMapping extends AttributeMapping implements EntityViewMethodAttributeMapping {

    private final String attributeName;
    private final Method method;
    private final Method setterMethod;
    private final int attributeIndex;

    private Map<String, Class<? extends AttributeFilterProvider<?>>> attributeFilterProviders;

    // Updatable configs
    private Boolean isUpdatable;
    private Boolean isOrphanRemoval;
    private Boolean isOptimisticLockProtected;
    private String mappedBy;
    private Map<EmbeddableOwner, String> embeddableMappedByMap;
    private InverseRemoveStrategy inverseRemoveStrategy;
    private Set<CascadeType> cascadeTypes = Collections.singleton(CascadeType.AUTO);
    private Set<Class<?>> cascadeSubtypeClasses;
    private Set<Class<?>> cascadePersistSubtypeClasses;
    private Set<Class<?>> cascadeUpdateSubtypeClasses;

    private Map<ViewMapping, Boolean> readOnlySubtypeMappings;
    private Map<ViewMapping, Boolean> cascadeSubtypeMappings;
    private Map<ViewMapping, Boolean> cascadePersistSubtypeMappings;
    private Map<ViewMapping, Boolean> cascadeUpdateSubtypeMappings;
    private Set<ManagedViewTypeImplementor<?>> readOnlySubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadeSubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadePersistSubtypes;
    private Set<ManagedViewTypeImplementor<?>> cascadeUpdateSubtypes;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableReadOnlySubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadeSubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadePersistSubtypesMap;
    private Map<EmbeddableOwner, Set<ManagedViewTypeImplementor<?>>> embeddableCascadeUpdateSubtypesMap;

    public MethodAttributeMapping(ViewMapping viewMapping, Annotation mapping, MappingIndex mappingIndex, MetamodelBootContext context, String attributeName, Method method, int attributeIndex, boolean isCollection, PluralAttribute.ElementCollectionType elementCollectionType, Class<?> declaredTypeClass, Class<?> declaredKeyTypeClass, Class declaredElementTypeClass,
                                  java.lang.reflect.Type type, java.lang.reflect.Type keyType, java.lang.reflect.Type elementType, Map<Class<?>, String> inheritanceSubtypeClassMappings, Map<Class<?>, String> keyInheritanceSubtypeClassMappings, Map<Class<?>, String> elementInheritanceSubtypeClassMappings) {
        super(viewMapping, mapping, mappingIndex, context, isCollection, elementCollectionType, declaredTypeClass, declaredKeyTypeClass, declaredElementTypeClass, type, keyType, elementType, inheritanceSubtypeClassMappings, keyInheritanceSubtypeClassMappings, elementInheritanceSubtypeClassMappings);
        this.attributeName = attributeName;
        this.method = method;
        this.attributeIndex = attributeIndex;
        Method setter = null;
        Method covariantGetter = null;
        List<Method> setters = ReflectionUtils.getSetters(viewMapping.getEntityViewClass(), attributeName);
        List<Method> illegalSetters = null;
        for (Method m : setters) {
            if ((m.getModifiers() & Modifier.ABSTRACT) != 0) {
                if (com.blazebit.reflection.ReflectionUtils.getResolvedMethodParameterTypes(viewMapping.getEntityViewClass(), m)[0].equals(com.blazebit.reflection.ReflectionUtils.getResolvedMethodReturnType(viewMapping.getEntityViewClass(), method))) {
                    setter = m;
                    break;
                } else {
                    // Before considering this illegal, let's consider that the getter could be covariant overridden
                    if (covariantGetter == null) {
                        covariantGetter = com.blazebit.reflection.ReflectionUtils.getMethod(viewMapping.getEntityViewClass(), method.getName());
                    }
                    if (com.blazebit.reflection.ReflectionUtils.getResolvedMethodParameterTypes(viewMapping.getEntityViewClass(), m)[0].equals(com.blazebit.reflection.ReflectionUtils.getResolvedMethodReturnType(viewMapping.getEntityViewClass(), covariantGetter))) {
                        setter = m;
                        break;
                    }
                    if (illegalSetters == null) {
                        illegalSetters = new ArrayList<>();
{'fraction_non_alphanumeric': 0.08418998048145739, 'fraction_numerical': 0.0025374105400130125, 'mean_word_length': 5.39658759883479, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6546702', 'n_tokens_mistral': 4260, 'n_tokens_neox': 4187, 'n_words': 821}