/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation 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
//      Gordon Yorke - VM managed entity detachment
//     Eduard Bartsch, SAP - Fix for Bug 351186 - ConcurrentModificationException Exception in PropertiesHandler
//     Rick Curtis - Add support for WebSphere Liberty platform.
//     08/11/2014-2.5 Rick Curtis
//       - 440594: Tolerate invalid NamedQuery at EntityManager creation.
//     09/03/2015 - Will Dazey
//       - 456067 : Added support for defining query timeout units
//     09/28/2015 - Will Dazey
//       - 478331 : Added support for defining local or server as the default locale for obtaining timestamps
//     03/11/2016 - Jody Grassel
//       - 489794 : Add support for WebSphere EJBEmbeddable platform.
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
//     04/11/2018 - Will Dazey
//       - 533148 : Add the eclipselink.jpa.sql-call-deferral property
package org.eclipse.persistence.internal.sessions;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import org.eclipse.persistence.annotations.IdValidation;
import org.eclipse.persistence.config.BatchWriting;
import org.eclipse.persistence.config.CacheType;
import org.eclipse.persistence.config.CommitOrderType;
import org.eclipse.persistence.config.EntityManagerProperties;
import org.eclipse.persistence.config.ExclusiveConnectionMode;
import org.eclipse.persistence.config.FlushClearCache;
import org.eclipse.persistence.config.LoggerType;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.config.TargetDatabase;
import org.eclipse.persistence.config.TargetServer;
import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetSystemProperty;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;

/**
 *
 * The class processes some of EclipseLink properties.
 * The class may be used for any properties, but it only makes sense
 * to use it in the following two cases:
 *      1. There is a set of legal values defined
 *          either requiring translation (like CacheTypeProp);
 *          or not (like LoggingLevelProp).
 *      2. Property is really a prefix from which the property obtained by
 *      appending entity or class name (like DescriptorCustomizerProp -
 *      it corresponds to "eclipselink.descriptor.customizer." prefix that allows to
 *      define properties like "eclipselink.descriptor.customizer.myPackage.MyClass").
 *
 * EclipseLink properties and their values defined in org.eclipse.persistence.config package.
 *
 * To add a new property:
 *   Define a new property in PersistenceUnitProperties;
 *   Add a class containing property's values if required to config package (like CacheType);
 *      Alternatively values may be already defined elsewhere (like in LoggingLevelProp).
 *   Add an inner class to this class extending Prop corresponding to the new property (like CacheTypeProp);
 *      The first constructor parameter is property name; the second is default value;
 *      In constructor
 *          provide 2-dimensional value array in case the values should be translated (like CacheTypeProp);
 *              in case translation is not required provide a single-dimension array (like LoggingLevelProp).
 *   In inner class Prop static initializer addProp an instance of the new prop class (like addProp(new CacheTypeProp())).
 *
 * @see PersistenceUnitProperties
 * @see CacheType
 * @see TargetDatabase
 * @see TargetServer
 *
 *  05/28/2008-1.0M8 Andrei Ilitchev.
 *     - 224964: Provide support for Proxy Authentication through JPA.
 *     Added support for CONNECTION_EXCLUSIVE. Also added BooleanProp to allow simpler way of creating boolean-valued properties:
 *     instead of defining a new class for each new Boolean property just add a new instance of BooleanProp with property name and default:
 *           addProp(new BooleanProp(PersistenceUnitProperties.CONNECTION_EXCLUSIVE, "false"));
 *     Changed the existing boolean-valued properties to use this approach, also
 *     applied the same approach to LOGGING_LEVEL and CATEGORY_LOGGING_LEVEL_
 *     Also introduced a new version of getSessionPropertyValue that takes properties:
 *         public static String getSessionPropertyValue(String name, Map m, AbstractSession session) {
 *     it's convenient for use in EntityManagerImpl: first searches the passed properties then (recursively) properties of the session, then System properties.
 */
public class PropertiesHandler {

    /**
     * INTERNAL:
     * Gets property value from the map, if none found looks in System properties.
     * Use this to get a value for a non-prefixed property.
     * Could be used on prefixes (like "org.eclipse.persistence.cache-type.") too,
     * but will always return null
     * Throws IllegalArgumentException in case the property value is illegal.
     */
    public static String getPropertyValue(String name, Map m) {
        return getPropertyValue(name, m, true);
    }

    public static String getPropertyValueLogDebug(String name, Map m, AbstractSession session) {
        return getPropertyValueLogDebug(name, m, session, true);
    }

    public static String getPropertyValue(String name, Map m, boolean useSystemAsDefault) {
        return Prop.getPropertyValueToApply(name, m, null, useSystemAsDefault);
    }

    public static String getPropertyValueLogDebug(String name, Map m, AbstractSession session, boolean useSystemAsDefault) {
        return Prop.getPropertyValueToApply(name, m, session, useSystemAsDefault);
    }

    /**
     * INTERNAL:
     * Given property name and value verifies and translates the value.
     * Throws IllegalArgumentException in case the property value is illegal.
     */
    public static String getPropertyValue(String name, String value) {
        return Prop.getPropertyValueToApply(name, value, null);
    }

    public static String getPropertyValueLogDebug(String name, String value, AbstractSession session) {
        return Prop.getPropertyValueToApply(name, value, session);
    }

    /**
     * INTERNAL:
     * Gets property value from the map, if none found looks in System properties.
     * Use this to get a value for a prefixed property:
     * for "org.eclipse.persistence.cache-type.Employee"
     * pass "org.eclipse.persistence.cache-type.", "Employee".
     * Throws IllegalArgumentException in case the property value is illegal.
     */
    public static String getPrefixedPropertyValue(String prefix, String suffix, Map m) {
        return (String)getPrefixValues(prefix, m).get(suffix);
    }

    /**
     * INTERNAL:
     * Gets properties' values from the map, if none found looks in System properties.
     * In the returned map values keyed by suffixes.
     * Use it with prefixes (like "org.eclipse.persistence.cache-type.").
     * Could be used on simple properties (not prefixes, too),
     * but will always return either an empty map or a map containing a single
     * value keyed by an empty String.
     * Throws IllegalArgumentException in case the property value is illegal.
     */
    public static Map getPrefixValues(String prefix, Map m) {
        return Prop.getPrefixValuesToApply(prefix, m, null, true);
    }

    public static Map getPrefixValuesLogDebug(String prefix, Map m, AbstractSession session) {
        return Prop.getPrefixValuesToApply(prefix, m, session, true);
    }

    /**
     * INTERNAL:
     * Returns the default property value that should be applied.
     * Throws IllegalArgumentException in case the name doesn't correspond
     * to any property.
     */
    public static String getDefaultPropertyValue(String name) {
        return Prop.getDefaultPropertyValueToApply(name, null);
    }

    public static String getDefaultPropertyValueLogDebug(String name, AbstractSession session) {
        return Prop.getDefaultPropertyValueToApply(name, session);
    }

    /**
     * INTERNAL:
     * Empty String value indicates that the default property value should be used.
     */
    protected static boolean shouldUseDefault(String value) {
        return value != null &&  value.length() == 0;
    }

    protected static abstract class Prop {
        static HashMap mainMap = new HashMap();
        Object[] valueArray;
        HashMap valueMap;
        String name;
        String defaultValue;
        String defaultValueToApply;
        boolean valueToApplyMayBeNull;
        boolean shouldReturnOriginalValueIfValueToApplyNotFound;

        static {
            addProp(new LoggerTypeProp());
            addProp(new LoggingLevelProp(PersistenceUnitProperties.LOGGING_LEVEL, Level.INFO.getName()));
            addProp(new LoggingLevelProp(PersistenceUnitProperties.CATEGORY_LOGGING_LEVEL_, Level.INFO.getName()));
            addProp(new TargetDatabaseProp());
            addProp(new TargetServerProp());
            addProp(new JTACntrlrProp());
            addProp(new CacheSizeProp());
            addProp(new CacheTypeProp());
            addProp(new BooleanProp(PersistenceUnitProperties.CACHE_SHARED_, "false"));
            addProp(new DescriptorCustomizerProp());
            addProp(new BatchWritingProp());
            addProp(new FlushClearCacheProp());
            addProp(new ReferenceModeProp());
            addProp(new FlushModeProp());
            addProp(new BooleanProp(PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.PERSISTENCE_CONTEXT_PERSIST_ON_COMMIT, "true"));
            addProp(new BooleanProp(PersistenceUnitProperties.PERSISTENCE_CONTEXT_COMMIT_WITHOUT_PERSIST_RULES, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.VALIDATE_EXISTENCE, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.ORDER_UPDATES, "true"));
            addProp(new CommitOrderProp());
            addProp(new BooleanProp(PersistenceUnitProperties.JOIN_EXISTING_TRANSACTION, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.COMPOSITE_UNIT, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.COMPOSITE_UNIT_MEMBER, "false"));
            addProp(new ExclusiveConnectionModeProp());
            addProp(new BooleanProp(PersistenceUnitProperties.EXCLUSIVE_CONNECTION_IS_LAZY, "true"));
            addProp(new IdValidationProp());
            addProp(new ConnectionPoolProp());
            addProp(new BooleanProp(PersistenceUnitProperties.JDBC_RESULT_SET_ACCESS_OPTIMIZATION, Boolean.toString(ObjectLevelReadQuery.isResultSetAccessOptimizedQueryDefault)));
            addProp(new BooleanProp(PersistenceUnitProperties.JPQL_TOLERATE, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, "true"));
            //Enhancement
            addProp(new QueryTimeoutUnitProp());
            addProp(new PessimisticLockTimeoutUnitProp());
            addProp(new BooleanProp(PersistenceUnitProperties.USE_LOCAL_TIMESTAMP, "false"));
            addProp(new BooleanProp(PersistenceUnitProperties.SQL_CALL_DEFERRAL, "true"));
            addProp(new BooleanProp(PersistenceUnitProperties.NAMING_INTO_INDEXED, "false"));
        }

        Prop(String name) {
            this.name = name;
        }

        Prop(String name, String defaultValue) {
            this(name);
            this.defaultValue = defaultValue;
        }

        static String getPropertyValueFromMap(String name, Map m, boolean useSystemAsDefault) {
            String value = (String)m.get(name);
            if (value == null && useSystemAsDefault) {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    value = AccessController.doPrivileged(new PrivilegedGetSystemProperty(name));
                } else {
                    value = System.getProperty(name);
                }
            }

            return value;
        }

        // Collect all entries corresponding to the prefix name.
        // Note that entries from Map m override those from System properties.
        static Map getPrefixValuesFromMap(String name, Map m, boolean useSystemAsDefault) {
            Map mapOut = new HashMap();

            if(useSystemAsDefault) {
                Map.Entry[] entries = (Map.Entry[]) AccessController.doPrivileged(new PrivilegedAction() {
                    @Override
                    public Object run() {
                        return System.getProperties().entrySet().toArray(new Map.Entry[] {});
                        }
                    }
                );

                for (Map.Entry entry:entries) {
                    String str = (String)entry.getKey();
                    if(str.startsWith(name)) {
                        String entityName = str.substring(name.length(), str.length());
                        mapOut.put(entityName, entry.getValue());
                    }
                }
            }

            Iterator it = m.entrySet().iterator();
            while(it.hasNext()) {
                Map.Entry entry = (Map.Entry)it.next();
                String str = (String)entry.getKey();
                if(str.startsWith(name)) {
                    String entityName = str.substring(name.length(), str.length());
                    mapOut.put(entityName, entry.getValue());
                }
            }

            return mapOut;
        }

        static String getPropertyValue(String name, boolean shouldUseDefault, Map m, AbstractSession session, boolean useSystemAsDefault) {
            Prop prop = (Prop)mainMap.get(name);
            if(prop == null) {
                // it's not our property
                return null;
            }
            String value = getPropertyValueFromMap(name, m, useSystemAsDefault);
            if(value == null) {
                return null;
            }
            return prop.getValueToApply(value, shouldUseDefault, session);
        }

        static String getPropertyValueToApply(String name, Map m, AbstractSession session, boolean useSystemAsDefault) {
            Prop prop = (Prop)mainMap.get(name);
            if(prop == null) {
                throw new IllegalArgumentException(name);
            }
            String value = getPropertyValueFromMap(name, m, useSystemAsDefault);
            if(value == null) {
                return null;
            }
            return prop.getValueToApply(value, shouldUseDefault(value), session);
        }

        static String getPropertyValueToApply(String name, String value, AbstractSession session) {
            Prop prop = (Prop)mainMap.get(name);
            if(prop == null) {
                throw new IllegalArgumentException(name);
            }
            return prop.getValueToApply(value, shouldUseDefault(value), session);
        }

        static Map<String, Object> getPrefixValuesToApply(String prefix, Map m, AbstractSession session, boolean useSystemAsDefault) {
            Prop prop = (Prop)mainMap.get(prefix);
            // maps suffixes to property values
            Map mapIn = getPrefixValuesFromMap(prefix, m, useSystemAsDefault);
            if(mapIn.isEmpty()) {
                return mapIn;
            }

            HashMap mapOut = new HashMap(mapIn.size());
            Iterator it = mapIn.entrySet().iterator();
            while(it.hasNext()) {
                Map.Entry entry = (Map.Entry)it.next();
                String suffix = (String)entry.getKey();
                Object value = entry.getValue();
                if ((prop != null) && (value instanceof String)) {
                    value = prop.getValueToApply((String)value, shouldUseDefault((String)value), suffix, session);
                }
                mapOut.put(suffix, value);
            }
            // maps suffixes to valuesToApply
            return mapOut;
        }

        static String getDefaultPropertyValueToApply(String name, AbstractSession session) {
            Prop prop = (Prop)mainMap.get(name);
            if(prop == null) {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-default-for-unknown-property", new Object[]{name}));
            }
            prop.logDefault(session);
            return prop.defaultValueToApply;
        }

        String getValueToApply(String value, boolean shouldUseDefault, AbstractSession session) {
            return getValueToApply(value, shouldUseDefault, null, session);
        }

        // suffix is used only for properties-prefixes (like CacheType)
        String getValueToApply(String value, boolean shouldUseDefault, String suffix, AbstractSession session) {
            if(shouldUseDefault) {
                logDefault(session, suffix);
                return defaultValueToApply;
            }
            String valueToApply = value;
            if(valueMap != null) {
                String key = getUpperCaseString(value);
                valueToApply = (String)valueMap.get(key);
                if(valueToApply == null) {
                    boolean notFound = true;
                    if(valueToApplyMayBeNull) {
                        notFound = !valueMap.containsKey(key);
                    }
                    if(notFound) {
                        if(shouldReturnOriginalValueIfValueToApplyNotFound) {
                            valueToApply = value;
                        } else {
                            String propertyName = name;
                            if(suffix != null) {
                                propertyName = propertyName + suffix;
                            }
                            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-illegal-property-value", new Object[]{propertyName, getPrintValue(value)}));
                        }
                    }
                }
            }
            String logValue = PersistenceUnitProperties.getOverriddenLogStringForProperty(name);
            if (logValue != null){
                log(session, logValue, logValue, suffix);
            } else {
                log(session, value, valueToApply, suffix);
            }
            return valueToApply;
        }

        static String getUpperCaseString(String value) {
            if(value != null) {
                return value.toUpperCase();
            } else {
                return null;
            }
        }
        static String getPrintValue(String value) {
            if(value != null) {
                return value;
            } else {
                return "null";
            }
        }
        void initialize() {
            if(valueArray != null) {
                valueMap = new HashMap(valueArray.length);
                if(valueArray instanceof Object[][]) {
                    Object[][] valueArray2 = (Object[][])valueArray;
                    for(int i=0; i<valueArray2.length; i++) {
                        valueMap.put(getUpperCaseString((String)valueArray2[i][0]), valueArray2[i][1]);
                        if(valueArray2[i][1] == null) {
                            valueToApplyMayBeNull = true;
                        }
                    }
                } else {
                    for(int i=0; i<valueArray.length; i++) {
                        valueMap.put(getUpperCaseString((String)valueArray[i]), valueArray[i]);
                        if(valueArray[i] == null) {
                            valueToApplyMayBeNull = true;
                        }
                    }
                }
                defaultValueToApply = (String)valueMap.get(getUpperCaseString(defaultValue));
            } else {
                defaultValueToApply = defaultValue;
            }
        }

        void logDefault(AbstractSession session) {
            logDefault(session, null);
        }

        void logDefault(AbstractSession session, String suffix) {
            if (session != null) {
                if (session.shouldLog(SessionLog.FINEST, SessionLog.PROPERTIES)) {
                    String propertyName = name;
                    if (suffix != null) {
                        propertyName = propertyName + suffix;
                    }
                    if (defaultValue != defaultValueToApply) {
                        session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "handler_property_value_default", new Object[]{propertyName, defaultValue, defaultValueToApply});
                    } else {
                        session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "property_value_default", new Object[]{propertyName, defaultValue});
                    }
                }
            }
        }

        void log(AbstractSession session, String value, String valueToApply, String suffix) {
            if (session != null) {
                if (session.shouldLog(SessionLog.FINEST, SessionLog.PROPERTIES)) {
                    String propertyName = name;
                    if(suffix != null) {
                        propertyName = propertyName + suffix;
                    }
                    if(value != valueToApply) {
                        session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "handler_property_value_specified", new Object[]{propertyName, value, valueToApply});
                    } else {
                        session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "property_value_specified", new Object[]{propertyName, value});
                    }
                }
            }
        }

        static void addProp(Prop prop) {
            prop.initialize();
            mainMap.put(prop.name, prop);
        }
    }

    protected static class LoggerTypeProp extends Prop {
        LoggerTypeProp() {
            super(PersistenceUnitProperties.LOGGING_LOGGER, LoggerType.DEFAULT);
            this.shouldReturnOriginalValueIfValueToApplyNotFound = true;
            String pcg = "org.eclipse.persistence.logging.";
            valueArray = new Object[][] {
                {LoggerType.DefaultLogger, pcg + "DefaultSessionLog"},
                {LoggerType.JavaLogger, pcg + "JavaLog"}
            };
        }
    }

    protected static class ConnectionPoolProp extends Prop {
        ConnectionPoolProp() {
            super(PersistenceUnitProperties.CONNECTION_POOL);
        }
    }

    protected static class LoggingLevelProp extends Prop {
        LoggingLevelProp(String name, String defaultValue) {
            super(name, defaultValue);
            valueArray = new Object[] {
                Level.OFF.getName(),
                Level.SEVERE.getName(),
                Level.OFF.getName(),
                Level.WARNING.getName(),
                Level.INFO.getName(),
                Level.CONFIG.getName(),
                Level.FINE.getName(),
                Level.FINER.getName(),
                Level.FINEST.getName(),
                Level.ALL.getName()
            };
        }
    }

    protected static class ReferenceModeProp extends Prop {
        ReferenceModeProp() {
            super(EntityManagerProperties.PERSISTENCE_CONTEXT_REFERENCE_MODE, ReferenceMode.HARD.toString());
            valueArray = new Object[] {
                ReferenceMode.HARD.toString(),
                ReferenceMode.WEAK.toString(),
                ReferenceMode.FORCE_WEAK.toString()
            };
        }
    }

    protected static class FlushModeProp extends Prop {
        FlushModeProp() {
            //XXX - using jakarta.persistence.FlushModeType.* directly causes
            //runtime dependency of this class on JPA API which is wrong
            //and leads to transitive dependency from MOXy to JPA API
            super(EntityManagerProperties.PERSISTENCE_CONTEXT_FLUSH_MODE,
                    /* FlushModeType.AUTO.toString() */ "AUTO");
            valueArray = new Object[] {
                    /* FlushModeType.AUTO.toString() */ "AUTO",
                    /* FlushModeType.COMMIT.toString() */"COMMIT"
            };
        }
    }

    protected static class CommitOrderProp extends Prop {
        CommitOrderProp() {
            super(EntityManagerProperties.PERSISTENCE_CONTEXT_COMMIT_ORDER, CommitOrderType.None);
            valueArray = new Object[] {
                    CommitOrderType.Id,
                    CommitOrderType.Changes,
                    CommitOrderType.None
            };
        }
    }

    protected static class TargetDatabaseProp extends Prop {
        TargetDatabaseProp() {
            super(PersistenceUnitProperties.TARGET_DATABASE, TargetDatabase.DEFAULT);
            this.shouldReturnOriginalValueIfValueToApplyNotFound = true;
            String pcg = "org.eclipse.persistence.platform.database.";
            valueArray = new Object[][] {
                {TargetDatabase.Auto, pcg + "DatabasePlatform"},
                {TargetDatabase.Oracle, pcg + "OraclePlatform"},
                {TargetDatabase.Oracle8, pcg + "oracle.Oracle8Platform"},
                {TargetDatabase.Oracle9, pcg + "oracle.Oracle9Platform"},
                {TargetDatabase.Oracle10, pcg + "oracle.Oracle10Platform"},
                {TargetDatabase.Oracle11, pcg + "oracle.Oracle11Platform"},
                {TargetDatabase.Attunity, pcg + "AttunityPlatform"},
                {TargetDatabase.Cloudscape, pcg + "CloudscapePlatform"},
                {TargetDatabase.Database, pcg + "DatabasePlatform"},
                {TargetDatabase.DB2Mainframe, pcg + "DB2MainframePlatform"},
                {TargetDatabase.DB2, pcg + "DB2Platform"},
                {TargetDatabase.DBase, pcg + "DBasePlatform"},
                {TargetDatabase.Derby, pcg + "DerbyPlatform"},
                {TargetDatabase.HANA,  pcg + "HANAPlatform"},
                {TargetDatabase.HSQL, pcg + "HSQLPlatform"},
                {TargetDatabase.Informix, pcg + "InformixPlatform"},
                {TargetDatabase.JavaDB, pcg + "JavaDBPlatform"},
                {TargetDatabase.MySQL, pcg + "MySQLPlatform"},
                {TargetDatabase.MaxDB, pcg + "MaxDBPlatform"},
                {TargetDatabase.MySQL4, pcg + "MySQLPlatform"}, // 211249: keep backwards compatibility
                {TargetDatabase.PointBase,  pcg + "PointBasePlatform"},
                {TargetDatabase.PostgreSQL,  pcg + "PostgreSQLPlatform"},
                {TargetDatabase.SQLAnywhere,  pcg + "SQLAnywherePlatform"},
                {TargetDatabase.SQLServer,  pcg + "SQLServerPlatform"},
                {TargetDatabase.Sybase,  pcg + "SybasePlatform"},
                {TargetDatabase.Symfoware,  pcg + "SymfowarePlatform"},
                {TargetDatabase.TimesTen,  pcg + "TimesTenPlatform"}
            };
        }
    }

    protected static class TargetServerProp extends Prop {
        TargetServerProp() {
            super(PersistenceUnitProperties.TARGET_SERVER, TargetServer.DEFAULT);
            this.shouldReturnOriginalValueIfValueToApplyNotFound = true;
            String pcg = "org.eclipse.persistence.platform.server.";
            valueArray = new Object[][] {
                {TargetServer.None, pcg + "NoServerPlatform"},
                {TargetServer.OC4J, pcg + "oc4j.Oc4jPlatform"},
                {TargetServer.Glassfish, pcg + "glassfish.GlassfishPlatform"},
                {TargetServer.WebSphere, pcg + "was.WebSpherePlatform"},
                {TargetServer.WebSphere_6_1, pcg + "was.WebSphere_6_1_Platform"},
                {TargetServer.WebSphere_7, pcg + "was.WebSphere_7_Platform"},
                {TargetServer.WebSphere_EJBEmbeddable, pcg + "was.WebSphere_EJBEmbeddable_Platform"},
                {TargetServer.WebSphere_Liberty, pcg + "was.WebSphere_Liberty_Platform"},
                {TargetServer.WebLogic, pcg + "wls.WebLogicPlatform"},
                {TargetServer.WebLogic_9, pcg + "wls.WebLogic_9_Platform"},
                {TargetServer.WebLogic_10, pcg + "wls.WebLogic_10_Platform"},
                {TargetServer.WebLogic_12, pcg + "wls.WebLogic_12_Platform"},
                {TargetServer.JBoss, pcg + "jboss.JBossPlatform"},
                {TargetServer.SAPNetWeaver_7_1, pcg + "sap.SAPNetWeaver_7_1_Platform"}
                };
        }
    }

    protected static class JTACntrlrProp extends Prop {
        JTACntrlrProp() {
            super(PersistenceUnitProperties.JTA_CONTROLLER);
        }
    }

    protected static class CacheSizeProp extends Prop {
        CacheSizeProp() {
            super(PersistenceUnitProperties.CACHE_SIZE_, Integer.toString(1000));
        }
    }

    protected static class CacheTypeProp extends Prop {
        CacheTypeProp() {
            super(PersistenceUnitProperties.CACHE_TYPE_, CacheType.DEFAULT);
            String pcg = "org.eclipse.persistence.internal.identitymaps.";
            valueArray = new Object[][] {
                {CacheType.Weak, pcg + "WeakIdentityMap"},
                {CacheType.Soft, pcg + "SoftIdentityMap"},
                {CacheType.SoftWeak, pcg + "SoftCacheWeakIdentityMap"},
                {CacheType.HardWeak, pcg + "HardCacheWeakIdentityMap"},
                {CacheType.Full, pcg + "FullIdentityMap"},
                {CacheType.NONE, pcg + "NoIdentityMap"}
            };
        }
    }

    protected static class BooleanProp extends Prop {
        BooleanProp(String name, String defaultValue) {
            super(name, defaultValue);
            valueArray = new Object[] {
                "true",
                "false"
            };
        }
    }

    protected static class DescriptorCustomizerProp extends Prop {
        DescriptorCustomizerProp() {
            super(PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_);
        }
    }

    protected static class BatchWritingProp extends Prop {
        BatchWritingProp() {
            super(PersistenceUnitProperties.BATCH_WRITING, BatchWriting.DEFAULT);
            this.shouldReturnOriginalValueIfValueToApplyNotFound = true;
            valueArray = new Object[] {
                BatchWriting.None,
                BatchWriting.JDBC,
                BatchWriting.Buffered,
                BatchWriting.OracleJDBC
            };
        }
    }

    protected static class FlushClearCacheProp extends Prop {
        FlushClearCacheProp() {
            super(PersistenceUnitProperties.FLUSH_CLEAR_CACHE, FlushClearCache.DEFAULT);
            valueArray = new Object[] {
                FlushClearCache.Merge,
                FlushClearCache.Drop,
                FlushClearCache.DropInvalidate
            };
        }
    }

    protected static class ExclusiveConnectionModeProp extends Prop {
        ExclusiveConnectionModeProp() {
            super(PersistenceUnitProperties.EXCLUSIVE_CONNECTION_MODE, ExclusiveConnectionMode.DEFAULT);
            valueArray = new Object[] {
                ExclusiveConnectionMode.Transactional,
                ExclusiveConnectionMode.Isolated,
                ExclusiveConnectionMode.Always
            };
        }
    }

    protected static class IdValidationProp extends Prop {
        IdValidationProp() {
            super(PersistenceUnitProperties.ID_VALIDATION, IdValidation.ZERO.toString());
            valueArray = new Object[] {
                IdValidation.NULL.toString(),
                IdValidation.ZERO.toString(),
                IdValidation.NEGATIVE.toString(),
                IdValidation.NONE.toString()
            };
        }
    }

    protected static class QueryTimeoutUnitProp extends Prop {
        QueryTimeoutUnitProp() {
            super(PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, DescriptorQueryManager.DefaultTimeoutUnit.toString());
            valueArray = new Object[] {
                TimeUnit.MILLISECONDS.toString(),
                TimeUnit.SECONDS.toString(),
                TimeUnit.MINUTES.toString()
            };
        }
    }

    protected static class PessimisticLockTimeoutUnitProp extends Prop {
        PessimisticLockTimeoutUnitProp() {
            super(PersistenceUnitProperties.PESSIMISTIC_LOCK_TIMEOUT_UNIT, DescriptorQueryManager.DefaultTimeoutUnit.toString());
            valueArray = new Object[] {
                TimeUnit.MILLISECONDS.toString(),
                TimeUnit.SECONDS.toString(),
                TimeUnit.MINUTES.toString()
            };
        }
    }
}
