/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//      //     30/05/2012-2.4 Guy Pelletier
//       - 354678: Temp classloader is still being used during metadata processing
package org.eclipse.persistence.mappings.converters;

import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.ClassNameConversionRequired;
import org.eclipse.persistence.internal.descriptors.TypeMapping;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.sessions.Session;

/**
 * <b>Purpose</b>: Object type converter is used to match a fixed number of database data values
 * to Java object value. It can be used when the values on the database and in the Java differ.
 * To create an object type converter, simply specify the set of conversion value pairs.
 * A default value and one-way conversion are also supported for legacy data situations.
 *
 * @author James Sutherland
 * @since Toplink 10
 */
public class ObjectTypeConverter implements Converter, ClassNameConversionRequired {
    // String type names and values set from JPA processing.
    protected String converterName;
    protected Class<?> dataType;
    protected String dataTypeName;
    protected Class<?> objectType;
    protected String objectTypeName;
    protected Map<String, String> conversionValueStrings;
    protected Map<String, String> addToAttributeOnlyConversionValueStrings;

    protected DatabaseMapping mapping;
    protected transient Map fieldToAttributeValues;
    protected Map attributeToFieldValues;
    protected transient Object defaultAttributeValue;
    protected String defaultAttributeValueString;
    protected transient Class<?> fieldClassification;
    protected transient String fieldClassificationName;

    /**
     * PUBLIC:
     * Default constructor.
     */
    public ObjectTypeConverter() {
        this.attributeToFieldValues = new HashMap(10);
        this.fieldToAttributeValues = new HashMap(10);
        this.conversionValueStrings = new HashMap<>(10);
        this.addToAttributeOnlyConversionValueStrings = new HashMap<>(10);
    }

    /**
     * PUBLIC:
     * Default constructor.
     */
    public ObjectTypeConverter(DatabaseMapping mapping) {
        this();
        this.mapping = mapping;
    }

    /**
     * PUBLIC:
     * A type conversion value is a two-way mapping from the database to the object.
     * The database value will be substituted for the object value when read,
     * and the object value will be substituted for database value when written.
     * Note that each field/attribute value must have one and only one attribute/field value to maintain a two-way mapping.
     */
    public void addConversionValue(Object fieldValue, Object attributeValue) {
        if (fieldValue == null) {
            fieldValue = Helper.NULL_VALUE;
        }

        if (attributeValue == null) {
            attributeValue = Helper.NULL_VALUE;
        }

        getFieldToAttributeValues().put(fieldValue, attributeValue);
        getAttributeToFieldValues().put(attributeValue, fieldValue);
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void addConversionValueStrings(String dataValue, String objectValue) {
        this.conversionValueStrings.put(dataValue, objectValue);
    }

    /**
     * PUBLIC:
     * An attribute only conversion value is a one-way mapping from the database to the object.
     * This can be used if multiple database values are desired to be mapped to the same object value.
     * Note that when written only the default value will be used for the attribute, not this value.
     */
    public void addToAttributeOnlyConversionValue(Object fieldValue, Object attributeValue) {
        if (fieldValue == null) {
            fieldValue = Helper.NULL_VALUE;
        }

        if (attributeValue == null) {
            attributeValue = Helper.NULL_VALUE;
        }

        getFieldToAttributeValues().put(fieldValue, attributeValue);
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void addToAttributeOnlyConversionValueStrings(String dataValue, String objectValue) {
        this.addToAttributeOnlyConversionValueStrings.put(dataValue, objectValue);
    }

    /**
     * INTERNAL:
     * Get the attribute to field mapping.
     */
    public Map getAttributeToFieldValues() {
        return attributeToFieldValues;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this converter to actual
     * class-based settings. This method is used when converting a project
     * that has been built with class names to a project with classes.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        if (dataTypeName != null) {
            dataType = loadClass(dataTypeName, classLoader);
        }

        if (objectTypeName != null) {
            objectType = loadClass(objectTypeName, classLoader);
        }

        if (objectType != null && dataType != null) {
            // Process the data to object mappings. The object and data values
            // should be primitive wrapper types so we can initialize the
            // conversion values now.
            for (String dataValue : conversionValueStrings.keySet()) {
                String objectValue = conversionValueStrings.get(dataValue);

                addConversionValue(initObject(dataType, dataValue, true), initObject(objectType, objectValue, false));
            }

            for (String dataValue : addToAttributeOnlyConversionValueStrings.keySet()) {
                String objectValue = addToAttributeOnlyConversionValueStrings.get(dataValue);

                addToAttributeOnlyConversionValue(initObject(dataType, dataValue, true), initObject(objectType, objectValue, false));
            }

            if (defaultAttributeValueString != null) {
                setDefaultAttributeValue(initObject(objectType, defaultAttributeValueString, false));
            }
        }
    }

    /**
     * Load the given class name with the given loader.
     */
    protected Class<?> loadClass(String className, ClassLoader classLoader) {
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedClassForName<>(className, true, classLoader));
                } catch (PrivilegedActionException e) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(className, e.getException());
                }
            } else {
                return PrivilegedAccessHelper.getClassForName(className, true, classLoader);
            }
        } catch (Exception exception) {
            throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception);
        }
    }


    /**
     * INTERNAL:
     * Returns the corresponding attribute value for the specified field value.
     */
    @Override
    public Object convertDataValueToObjectValue(Object fieldValue, Session session) {
        Object attributeValue = null;

        if (fieldValue == null) {
            attributeValue = getFieldToAttributeValues().get(Helper.NULL_VALUE);
        } else {
            try {
                fieldValue = session.getDatasourcePlatform().getConversionManager().convertObject(fieldValue, getFieldClassification());
            } catch (ConversionException e) {
                throw ConversionException.couldNotBeConverted(mapping, mapping.getDescriptor(), e);
            }

            attributeValue = getFieldToAttributeValues().get(fieldValue);
            if (attributeValue == null) {
                if (getDefaultAttributeValue() != null) {
                    attributeValue = getDefaultAttributeValue();
                } else {
                    // CR#3779
                    throw DescriptorException.noFieldValueConversionToAttributeValueProvided(fieldValue, getMapping().getField(), getMapping());
                }
            }
        }
        return attributeValue;
    }

    /**
     * PUBLIC:
     * The default value can be used if the database can possibly store additional values then those that
     * have been mapped.  Any value retreived from the database that is not mapped will be substitued for the default value.
     */
    public Object getDefaultAttributeValue() {
        return defaultAttributeValue;
    }

    /**
     * INTERNAL:
     * Return the mapping.
     */
    protected DatabaseMapping getMapping() {
        return mapping;
    }

    /**
     * INTERNAL:
     * Set the mapping.
     */
    protected void setMapping(DatabaseMapping mapping) {
        this.mapping = mapping;
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void setObjectTypeName(String objectTypeName) {
        this.objectTypeName = objectTypeName;
    }

    /**
     * INTERNAL:
     * Get the type of the field value to allow conversion from the database.
     */
    public Class<?> getFieldClassification() {
        return fieldClassification;
    }

    public String getFieldClassificationName() {
        if ((fieldClassificationName == null) && (fieldClassification != null)) {
            fieldClassificationName = fieldClassification.getName();
        }
        return fieldClassificationName;
    }

    /**
     * INTERNAL:
     * Return the classifiction for the field contained in the mapping.
     * This is used to convert the row value to a consistent java value.
     * By default this is null which means unknown.
     */
    public Class<?> getFieldClassification(DatabaseField fieldToClassify) {
        return getFieldClassification();
    }

    /**
     * INTERNAL:
     * Return a collection of the field to attribute value associations.
     */
    public Vector getFieldToAttributeValueAssociations() {
        Vector associations = new Vector(getFieldToAttributeValues().size());
        Iterator fieldValueEnum = getFieldToAttributeValues().keySet().iterator();
        Iterator attributeValueEnum = getFieldToAttributeValues().values().iterator();
        while (fieldValueEnum.hasNext()) {
            Object fieldValue = fieldValueEnum.next();
            if (fieldValue == Helper.NULL_VALUE) {
                fieldValue = null;
            }
            Object attributeValue = attributeValueEnum.next();
            if (attributeValue == Helper.NULL_VALUE) {
                attributeValue = null;
            }
            associations.addElement(new TypeMapping(fieldValue, attributeValue));
        }

        return associations;
    }

    /**
     * INTERNAL:
     * Get the field to attribute mapping.
     */
    public Map getFieldToAttributeValues() {
        if (fieldToAttributeValues == null) {
            fieldToAttributeValues = new HashMap(10);
        }
        return fieldToAttributeValues;
    }

    /**
     *  INTERNAL:
     *  Convert to the data value.
     */
    @Override
    public Object convertObjectValueToDataValue(Object attributeValue, Session session) {
        Object fieldValue;
        if (attributeValue == null) {
            fieldValue = getAttributeToFieldValues().get(Helper.NULL_VALUE);
        } else {
            fieldValue = getAttributeToFieldValues().get(attributeValue);
            if (fieldValue == null) {
                throw DescriptorException.noAttributeValueConversionToFieldValueProvided(attributeValue, getMapping());
            }
        }
        return fieldValue;
    }


    /**
     * PUBLIC:
     * This is a very specific protocol which maps fieldValues "T" and "F"
     * to true and false respectively.
     */
    public void mapBooleans() {
        addConversionValue("F", Boolean.FALSE);
        addConversionValue("T", Boolean.TRUE);
    }

    /**
     * PUBLIC:
     * This is a very specific protocol which maps fieldValues "F" and "M"
     * to "Female" and "Male" respectively.
     */
    public void mapGenders() {
        addConversionValue("F", "Female");
        addConversionValue("M", "Male");
    }

    /**
     * PUBLIC:
     * This is a very specific protocol which maps fieldValues "Y" and "N"
     * to "Yes" and "No" respectively.
     */
    public void mapResponses() {
        addConversionValue("Y", "Yes");
        addConversionValue("N", "No");
    }

    /**
     * INTERNAL:
     * Set the field classification through searching the fields map.
     */
    public void initializeFieldClassification(Session session) throws DescriptorException {
        if (getFieldToAttributeValues().isEmpty()) {
            return;
        }
        Class<?> type = null;
        Iterator fieldValuesEnum = getFieldToAttributeValues().keySet().iterator();
        while (fieldValuesEnum.hasNext() && (type == null)) {
            Object value = fieldValuesEnum.next();
            if (value != Helper.NULL_VALUE) {
                type = value.getClass();
            }
        }

        setFieldClassification(type);
        // CR#... Mapping must also have the field classification.
        if (getMapping().isDirectToFieldMapping()) {
            AbstractDirectMapping directMapping = (AbstractDirectMapping)getMapping();

            // Allow user to specify field type to override computed value. (i.e. blob, nchar)
            if (directMapping.getFieldClassification() == null) {
                directMapping.setFieldClassification(type);
            }
        }
    }

    /**
     * INTERNAL:
     * Used to initialize string based conversion values set from JPA processing.
     */
    private Object initObject(Class<?> type, String value, boolean isData) {
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
            try {
                Constructor<?> constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<>(type, new Class<?>[] {String.class}, false));
                return AccessController.doPrivileged(new PrivilegedInvokeConstructor<>(constructor, new Object[] {value}));
            } catch (PrivilegedActionException exception) {
                throwInitObjectException(exception, type, value, isData);
            }
        } else {
            try {
                Constructor<?> constructor = PrivilegedAccessHelper.getConstructorFor(type, new Class<?>[] {String.class}, false);
                return PrivilegedAccessHelper.invokeConstructor(constructor, new Object[] {value});
            } catch (Exception exception) {
                throwInitObjectException(exception, type, value, isData);
            }
        }

        return null; // keep compiler happy, will never hit.
    }

    /**
     * INTERNAL:
     * Set the mapping.
     */
    @Override
    public void initialize(DatabaseMapping mapping, Session session) {
        this.mapping = mapping;
        initializeFieldClassification(session);
    }

    /**
     * INTERNAL:
     * Set the attribute to field mapping.
     */
    public void setAttributeToFieldValues(Map attributeToFieldValues) {
        this.attributeToFieldValues = attributeToFieldValues;
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void setConverterName(String converterName) {
        this.converterName = converterName;
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void setDataTypeName(String dataTypeName) {
        this.dataTypeName = dataTypeName;
    }

    /**
     * PUBLIC:
     * The default value can be used if the database can possibly store additional values then those that
     * have been mapped.  Any value retreived from the database that is not mapped will be substitued for the default value.
     */
    public void setDefaultAttributeValue(Object defaultAttributeValue) {
        this.defaultAttributeValue = defaultAttributeValue;
    }

    /**
     * INTERNAL:
     * Set from JPA processing where we deal with strings only to avoid
     * class loader conflicts.
     */
    public void setDefaultAttributeValueString(String defaultAttributeValueString) {
        this.defaultAttributeValueString = defaultAttributeValueString;
    }

    /**
     * INTERNAL:
     * Set the type of the field value to allow conversion from the database.
     */
    public void setFieldClassification(Class<?> fieldClassification) {
        this.fieldClassification = fieldClassification;
    }

    public void setFieldClassificationName(String fieldClassificationName) {
        this.fieldClassificationName = fieldClassificationName;
    }

    /**
     * INTERNAL:
     * Set a collection of the field to attribute value associations.
     */
    public void setFieldToAttributeValueAssociations(Vector fieldToAttributeValueAssociations) {
        setFieldToAttributeValues(new HashMap(fieldToAttributeValueAssociations.size() + 1));
        setAttributeToFieldValues(new HashMap(fieldToAttributeValueAssociations.size() + 1));
        for (Enumeration associationsEnum = fieldToAttributeValueAssociations.elements();
                 associationsEnum.hasMoreElements();) {
            Association association = (Association)associationsEnum.nextElement();
            addConversionValue(association.getKey(), association.getValue());
        }
    }

    /**
     * INTERNAL:
     * Set the field to attribute mapping.
     */
    public void setFieldToAttributeValues(Map fieldToAttributeValues) {
        this.fieldToAttributeValues = fieldToAttributeValues;
    }

    /**
     * INTERNAL:
     * If the converter converts the value to a non-atomic value, i.e.
     * a value that can have its' parts changed without being replaced,
     * then it must return false, serialization can be non-atomic.
     */
    @Override
    public boolean isMutable() {
        return false;
    }

    /**
     * INTERNAL:
     */
    protected void throwInitObjectException(Exception exception, Class<?> type, String value, boolean isData) {
        if (isData) {
            throw ValidationException.errorInstantiatingConversionValueData(converterName, value, type, exception);
        } else {
            throw ValidationException.errorInstantiatingConversionValueObject(converterName, value, type, exception);
        }
    }
}
