/*
 * 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.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.EnumSet;
import java.util.Iterator;

import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.sessions.Session;

/**
 * <b>Purpose</b>: Object type converter is used to match a fixed number of
 * database data values to a Java enum 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 Guy Pelletier
 * @since Toplink 10.1.4RI
 */
public class EnumTypeConverter extends ObjectTypeConverter {
    private Class m_enumClass;
    private String m_enumClassName;
    private boolean m_useOrdinalValues;

    /**
     * PUBLIC:
     * Creating an enum converter this way will create the conversion values
     * for you using ordinal or name values.
     */
    public EnumTypeConverter(DatabaseMapping mapping, Class<?> enumClass, boolean useOrdinalValues) {
        super(mapping);
        m_enumClass = enumClass;
        m_enumClassName = enumClass.getName();
        m_useOrdinalValues = useOrdinalValues;
        initializeConversions(m_enumClass);
    }

    /**
     * PUBLIC:
     * Creating an enum converter this way will create the conversion values
     * for you using ordinal or name values.
     */
    public EnumTypeConverter(DatabaseMapping mapping, String enumClassName, boolean useOrdinalValues) {
        this(mapping, enumClassName);
        m_useOrdinalValues = useOrdinalValues;
    }

    /**
     * PUBLIC:
     * Creating an enum converter this way expects that you will provide
     * the conversion values separately.
     */
    public EnumTypeConverter(DatabaseMapping mapping, String enumClassName) {
        super(mapping);
        m_enumClassName = enumClassName;
    }

    protected void initializeConversions(Class enumClass) {
        // Initialize conversion if not already set by Converter
        if (getFieldToAttributeValues().isEmpty()) {
            EnumSet theEnums = EnumSet.allOf(enumClass);
            Iterator<Enum> i = theEnums.iterator();

            while (i.hasNext()) {
                Enum theEnum = i.next();

                if (m_useOrdinalValues) {
                    addConversionValue(theEnum.ordinal(), theEnum.name());
                } else {
                    addConversionValue(theEnum.name(), theEnum.name());
                }
            }
        }
    }

    public Class<?> getEnumClass() {
        return m_enumClass;
    }

    public String getEnumClassName() {
        return m_enumClassName;
    }

    /**
     * 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) {
        super.convertClassNamesToClasses(classLoader);

        // convert if enumClass is null or if different classLoader
        if (m_enumClass == null || !m_enumClass.getClassLoader().equals(classLoader)) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        m_enumClass = AccessController.doPrivileged(
                            new PrivilegedClassForName<>(m_enumClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(
                            m_enumClassName, exception.getException());
                    }
                } else {
                    m_enumClass = PrivilegedAccessHelper.getClassForName(m_enumClassName, true,
                        classLoader);
                }
            } catch (ClassNotFoundException exception){
                throw ValidationException.classNotFoundWhileConvertingClassNames(m_enumClassName,
                    exception);
            }
        }
        initializeConversions(m_enumClass);
    }

    /**
     * INTERNAL:
     * Returns the corresponding attribute value for the specified field value.
     * Wraps the super method to return an Enum type from the string conversion.
     */
    @Override
    public Object convertDataValueToObjectValue(Object fieldValue, Session session) {
        Object obj = super.convertDataValueToObjectValue(fieldValue, session);

        if (fieldValue == null || obj == null) {
            return obj;
        } else {
            return Enum.valueOf(m_enumClass, (String) obj);
        }
    }

    /**
     * INTERNAL:
     * Convert Enum object to the data value. Internal enums are stored as
     * strings (names) so this method wraps the super method in that if
     * breaks down the enum to a string name before converting it.
     */
    @Override
    public Object convertObjectValueToDataValue(Object attributeValue, Session session) {
        if (attributeValue == null) {
            return super.convertObjectValueToDataValue(null, session);
        } else {
            return super.convertObjectValueToDataValue(((Enum)attributeValue).name(), session);
        }
    }
}
