| /* |
| * 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); |
| } |
| } |
| } |