/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation. 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
//     dminsky - added countOccurrencesOf(Object, List) API
//     08/23/2010-2.2 Michael O'Brien
//        - 323043: application.xml module ordering may cause weaving not to occur causing an NPE.
//                       warn if expected "_persistence_//_vh" method not found
//                       instead of throwing NPE during deploy validation.
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
package org.eclipse.persistence.internal.helper;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Vector;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.eclipse.persistence.config.SystemProperties;
import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.core.helper.CoreHelper;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetField;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * INTERNAL:
 * <p>
 * <b>Purpose</b>: Define any useful methods that are missing from the base Java.
 */
public class Helper extends CoreHelper implements Serializable {

    /** Used to configure JDBC level date optimization. */
    public static boolean shouldOptimizeDates = false;

    /** Used to store null values in hashtables, is helper because need to be serializable. */
    public static final Object NULL_VALUE = new Helper();

    /** Used to convert {@code null} value to {@link String}. */
    private static final String NULL_STRING = "null";

    /** PERF: Used to cache a set of calendars for conversion/printing purposes. */
    protected static final Queue<Calendar> calendarCache = initCalendarCache();

    /** PERF: Cache default timezone for calendar conversion. */
    protected static final TimeZone defaultTimeZone = TimeZone.getDefault();

    private static java.time.format.DateTimeFormatter dateTimeFormatter;

    // Changed static initialization to lazy initialization for bug 2756643

    /** Store CR string, for some reason \n is not platform independent. */
    protected static String CR;

    /** formatting strings for indenting */
    public static final String SPACE = " ";
    public static final String INDENT = "  ";

    /** Store newline string */
    public static final String NL = "\n";

    /** Prime the platform-dependent path separator */
    protected static String PATH_SEPARATOR = null;

    /** Prime the platform-dependent file separator */
    protected static String FILE_SEPARATOR = null;

    /** Prime the platform-dependent current working directory */
    protected static String CURRENT_WORKING_DIRECTORY = null;

    /** Prime the platform-dependent temporary directory */
    protected static String TEMP_DIRECTORY = null;

    /** Backdoor to allow 0 to be used in primary keys.
     * @deprecated
     * Instead of setting the flag to true use:
     * session.getProject().setDefaultIdValidation(IdValidation.NULL)
     **/
    @Deprecated
    public static boolean isZeroValidPrimaryKey = false;

    // settings to allow ascertaining attribute names from method names
    public static final String IS_PROPERTY_METHOD_PREFIX = "is";
    public static final String GET_PROPERTY_METHOD_PREFIX = "get";
    public static final String SET_PROPERTY_METHOD_PREFIX = "set";
    public static final String SET_IS_PROPERTY_METHOD_PREFIX = "setIs";
    public static final int POSITION_AFTER_IS_PREFIX = IS_PROPERTY_METHOD_PREFIX.length();
    public static final int POSITION_AFTER_GET_PREFIX = GET_PROPERTY_METHOD_PREFIX.length();

    public static final String DEFAULT_DATABASE_DELIMITER = "\"";

    public static final String PERSISTENCE_SET = "_persistence_set_";
    public static final String PERSISTENCE_GET = "_persistence_get_";
    // 323403: These constants are used to search for missing weaved functions - this is a copy is of the jpa project under ClassWeaver
    public static final String PERSISTENCE_FIELDNAME_PREFIX = "_persistence_";
    public static final String PERSISTENCE_FIELDNAME_POSTFIX = "_vh";

    private static String defaultStartDatabaseDelimiter = null;
    private static String defaultEndDatabaseDelimiter = null;

    /**
     * Return if JDBC date access should be optimized.
     */
    public static boolean shouldOptimizeDates() {
        return shouldOptimizeDates;
    }

    /**
     * Return if JDBC date access should be optimized.
     */
    public static void setShouldOptimizeDates(boolean value) {
        shouldOptimizeDates = value;
    }

    /**
     * PERF:
     * Return the calendar cache use to avoid calendar creation for processing java.sql/util.Date/Time/Timestamp objects.
     */
    public static Queue<Calendar> getCalendarCache() {
        return calendarCache;
    }

    /**
     * PERF:
     * Init the calendar cache use to avoid calendar creation for processing java.sql/util.Date/Time/Timestamp objects.
     */
    public static Queue initCalendarCache() {
        Queue calendarCache = new ConcurrentLinkedQueue();
        for (int index = 0; index < 10; index++) {
            calendarCache.add(Calendar.getInstance());
        }
        return calendarCache;
    }

    /**
     * PERF: This is used to optimize Calendar conversion/printing.
     * This should only be used when a calendar is temporarily required,
     * when finished it must be released back.
     */
    public static Calendar allocateCalendar() {
        Calendar calendar = getCalendarCache().poll();
        if (calendar == null) {
            calendar = Calendar.getInstance();
        }
        return calendar;
    }

    /**
     * PERF: Return the cached default platform.
     * Used for ensuring Calendar are in the local timezone.
     * The JDK method clones the timezone, so cache it locally.
     */
    public static TimeZone getDefaultTimeZone() {
        return defaultTimeZone;
    }

    public static java.time.format.DateTimeFormatter getDefaultDateTimeFormatter() {
        if (dateTimeFormatter == null) {
            dateTimeFormatter = new java.time.format.DateTimeFormatterBuilder()
                    .append(new java.time.format.DateTimeFormatterBuilder()
                            .parseCaseInsensitive()
                            .parseLenient()
                            .optionalStart()
                            .append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE)
                            .optionalEnd()
                            .optionalStart()
                            .appendLiteral('T')
                            .optionalEnd()
                            .optionalStart()
                            .append(java.time.format.DateTimeFormatter.ISO_LOCAL_TIME)
                            .optionalEnd()
                            .toFormatter())
                    .optionalStart()
                    .appendOffsetId()
                    .optionalStart()
                    .appendLiteral('[')
                    .parseCaseSensitive()
                    .appendZoneRegionId()
                    .appendLiteral(']')
                    .toFormatter();
        }
        return dateTimeFormatter;
    }

    /**
     * PERF: This is used to optimize Calendar conversion/printing.
     * This should only be used when a calendar is temporarily required,
     * when finished it must be released back.
     */
    public static void releaseCalendar(Calendar calendar) {
        getCalendarCache().offer(calendar);
    }

    public static void addAllToVector(Vector theVector, Vector elementsToAdd) {
        for (Enumeration stream = elementsToAdd.elements(); stream.hasMoreElements();) {
            theVector.addElement(stream.nextElement());
        }
    }

    public static Vector addAllUniqueToVector(Vector objects, List objectsToAdd) {
        if (objectsToAdd == null) {
            return objects;
        }
        int size = objectsToAdd.size();
        for (int index = 0; index < size; index++) {
            Object element = objectsToAdd.get(index);
            if (!objects.contains(element)) {
                objects.add(element);
            }
        }
        return objects;
    }

    public static List addAllUniqueToList(List objects, List objectsToAdd) {
        if (objectsToAdd == null) {
            return objects;
        }
        int size = objectsToAdd.size();
        for (int index = 0; index < size; index++) {
            Object element = objectsToAdd.get(index);
            if (!objects.contains(element)) {
                objects.add(element);
            }
        }
        return objects;
    }

    /**
    * Convert the specified vector into an array.
    */
    public static Object[] arrayFromVector(Vector vector) {
        Object[] result = new Object[vector.size()];
        for (int i = 0; i < vector.size(); i++) {
            result[i] = vector.elementAt(i);
        }
        return result;
    }

    /**
     * Convert {@link Integer} to hexadecimal {@link String}.
     * @param i An {@link Integer} to be converted to a hexadecimal string.
     * @return The {@link String} representation of the unsigned integer value represented by the argument
     *         in hexadecimal or {@code "null"} if provided {@link Integer} argument is {@code null}.
     */
    public static String integerToHexString(final Integer i) {
        return i != null ? Integer.toHexString(i) : NULL_STRING;
    }

    /**
     * Convert the HEX string to a byte array.
     * HEX allows for binary data to be printed.
     */
    public static byte[] buildBytesFromHexString(String hex) {
        String tmpString = hex;
        if ((tmpString.length() % 2) != 0) {
            throw ConversionException.couldNotConvertToByteArray(hex);
        }
        byte[] bytes = new byte[tmpString.length() / 2];
        int byteIndex;
        int strIndex;
        byte digit1;
        byte digit2;
        for (byteIndex = bytes.length - 1, strIndex = tmpString.length() - 2; byteIndex >= 0;
                 byteIndex--, strIndex -= 2) {
            digit1 = (byte)Character.digit(tmpString.charAt(strIndex), 16);
            digit2 = (byte)Character.digit(tmpString.charAt(strIndex + 1), 16);
            if ((digit1 == -1) || (digit2 == -1)) {
                throw ConversionException.couldNotBeConverted(hex, ClassConstants.APBYTE);
            }
            bytes[byteIndex] = (byte)((digit1 * 16) + digit2);
        }
        return bytes;
    }

    /**
     * Convert the byte array to a HEX string.
     * HEX allows for binary data to be printed.
     */
    public static String buildHexStringFromBytes(byte[] bytes) {
        char[] hexArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        StringBuilder stringBuilder = new StringBuilder();
        int tempByte;
        for (int byteIndex = 0; byteIndex < (bytes).length; byteIndex++) {
            tempByte = (bytes)[byteIndex];
            if (tempByte < 0) {
                tempByte = tempByte + 256;//compensate for the fact that byte is signed in Java
            }
            tempByte = (byte)(tempByte / 16);//get the first digit
            if (tempByte > 16) {
                throw ConversionException.couldNotBeConverted(bytes, ClassConstants.STRING);
            }
            stringBuilder.append(hexArray[tempByte]);

            tempByte = (bytes)[byteIndex];
            if (tempByte < 0) {
                tempByte = tempByte + 256;
            }
            tempByte = (byte)(tempByte % 16);//get the second digit
            if (tempByte > 16) {
                throw ConversionException.couldNotBeConverted(bytes, ClassConstants.STRING);
            }
            stringBuilder.append(hexArray[tempByte]);
        }
        return stringBuilder.toString();
    }

    /**
      * Create a new Vector containing all of the map elements.
      */
    public static Vector buildVectorFromMapElements(Map map) {
        Vector vector = new Vector(map.size());
        Iterator iterator = map.values().iterator();

        while (iterator.hasNext()) {
            vector.addElement(iterator.next());
        }

        return vector;
    }

    /**
     * Answer a Calendar from a date.
     */
    public static Calendar calendarFromUtilDate(java.util.Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //In jdk1.3, millisecond is missing
        if (date instanceof Timestamp) {
            calendar.set(Calendar.MILLISECOND, ((Timestamp)date).getNanos() / 1000000);
        }
        return calendar;
    }

    /**
     * INTERNAL:
     * Return whether a Class implements a specific interface, either directly or indirectly
     * (through interface or implementation inheritance).
     * @return boolean
     */
    public static boolean classImplementsInterface(Class aClass, Class anInterface) {
        // quick check
        if (aClass == anInterface) {
            return true;
        }

        Class[] interfaces = aClass.getInterfaces();

        // loop through the "directly declared" interfaces
        for (int i = 0; i < interfaces.length; i++) {
            if (interfaces[i] == anInterface) {
                return true;
            }
        }

        // recurse through the interfaces
        for (int i = 0; i < interfaces.length; i++) {
            if (classImplementsInterface(interfaces[i], anInterface)) {
                return true;
            }
        }

        // finally, recurse up through the superclasses to Object
        Class superClass = aClass.getSuperclass();
        if (superClass == null) {
            return false;
        }
        return classImplementsInterface(superClass, anInterface);
    }

    /**
     * INTERNAL:
     * Return whether a Class is a subclass of, or the same as, another Class.
     * @return boolean
     */
    public static boolean classIsSubclass(Class subClass, Class superClass) {
        Class temp = subClass;

        if (superClass == null) {
            return false;
        }

        while (temp != null) {
            if (temp == superClass) {
                return true;
            }
            temp = temp.getSuperclass();
        }
        return false;
    }

    /**
     * INTERNAL:
     * Compares two version in num.num.num.num.num*** format.
     * -1, 0, 1 means the version1 is less than, equal, greater than version2.
     * Example: compareVersions("11.1.0.6.0-Production", "11.1.0.7") == -1
     * Example: compareVersions("WebLogic Server 10.3.4", "10.3.3.0") == 1
     */
    public static int compareVersions(String version1, String version2) {
        return compareVersions(version(version1), version(version2));
    }

    /**
     * INTERNAL:
     * Expects version in ***num.num.num.num.num*** format, converts it to a List of Integers.
     * Example: "11.1.0.6.0_Production" -&gt; {11, 1, 0, 6, 0}
     * Example: "WebLogic Server 10.3.3.0" -&gt; {10, 3, 3, 0}
     */
    static protected List<Integer> version(String version) {
        ArrayList<Integer> list = new ArrayList<>(5);
        // first char - a digit - in the string corresponding to the current list index
        int iBegin = -1;
        // used to remove a non-digital prefix
        boolean isPrefix = true;
        for(int i=0; i<version.length(); i++) {
            char ch = version.charAt(i);
            if('0' <= ch && ch <= '9') {
                isPrefix = false;
                // it's a digit
                if(iBegin == -1) {
                    iBegin = i;
                }
            } else {
                // it's not a digit - try to create a number ending on the previous char - unless it's still part of the non-digital prefix.
                if(iBegin == -1) {
                    if(!isPrefix) {
                        break;
                    }
                } else {
                    isPrefix = false;
                    String strNum = version.substring(iBegin, i);
                    int num = Integer.parseInt(strNum, 10);
                    list.add(num);
                    iBegin = -1;
                    if(ch != '.') {
                        break;
                    }
                }
            }
        }
        if(iBegin >= 0) {
            String strNum = version.substring(iBegin, version.length());
            int num = Integer.parseInt(strNum, 10);
            list.add(num);
        }
        return list;
    }

    /**
     * INTERNAL:
     * Compares two lists of Integers
     * -1, 0, 1 means the first list is less than, equal, greater than the second list.
     * Example: {11, 1, 0, 6, 0} &lt; {11, 1, 0, 7}
     */
    static protected int compareVersions(List<Integer> list1, List<Integer>list2) {
        int n = Math.max(list1.size(), list2.size());
        int res = 0;
        for(int i=0; i<n; i++) {
            int l1 = 0;
            if(i < list1.size()) {
                l1 = list1.get(i);
            }
            int l2 = 0;
            if(i < list2.size()) {
                l2 = list2.get(i);
            }
            if(l1 < l2) {
                res =-1;
                break;
            } else if(l1 > l2) {
                res = 1;
                break;
            }
        }
        return res;
    }

    public static Class getClassFromClasseName(String className, ClassLoader classLoader){
        Class convertedClass = null;
        if(className==null){
            return null;
        }
        try{
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    convertedClass = AccessController.doPrivileged(new PrivilegedClassForName(className, true, classLoader));
                } catch (PrivilegedActionException exception) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception.getException());
                }
            } else {
                convertedClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, classLoader);
            }
            return convertedClass;
        } catch (ClassNotFoundException exc){
            throw ValidationException.classNotFoundWhileConvertingClassNames(className, exc);
        }
    }

    public static String getComponentTypeNameFromArrayString(String aString) {
        if (aString == null || aString.length() == 0) {
            return null;
        }
        // complex array component type case
        if (aString.length() > 3 && (aString.startsWith("[L") && aString.endsWith(";"))) {
            return aString.substring(2, aString.length() - 1);
        } else if (aString.startsWith("[")){
            Class primitiveClass = null;
            try {
                primitiveClass = Class.forName(aString);
            } catch (ClassNotFoundException cnf) {
                // invalid name specified - do not rethrow exception
                primitiveClass = null;
            }
            if (primitiveClass != null) {
                return primitiveClass.getComponentType().getName();
            }
        }
        return null;
    }

    public static boolean compareArrays(Object[] array1, Object[] array2) {
        if (array1.length != array2.length) {
            return false;
        }
        for (int index = 0; index < array1.length; index++) {
            //Related to Bug#3128838 fix.  ! is added to correct the logic.
            if(array1[index] != null) {
                if (!array1[index].equals(array2[index])) {
                    return false;
                }
            } else {
                if(array2[index] != null) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Compare two BigDecimals.
     * This is required because the .equals method of java.math.BigDecimal ensures that
     * the scale of the two numbers are equal. Therefore 0.0 != 0.00.
     * @see java.math.BigDecimal#equals(Object)
     */
    public static boolean compareBigDecimals(java.math.BigDecimal one, java.math.BigDecimal two) {
        if (one.scale() != two.scale()) {
            double doubleOne = (one).doubleValue();
            double doubleTwo = (two).doubleValue();
            if ((doubleOne != Double.POSITIVE_INFINITY) && (doubleOne != Double.NEGATIVE_INFINITY) && (doubleTwo != Double.POSITIVE_INFINITY) && (doubleTwo != Double.NEGATIVE_INFINITY)) {
                return doubleOne == doubleTwo;
            }
        }
        return one.equals(two);
    }

    public static boolean compareByteArrays(byte[] array1, byte[] array2) {
        if (array1.length != array2.length) {
            return false;
        }
        for (int index = 0; index < array1.length; index++) {
            if (array1[index] != array2[index]) {
                return false;
            }
        }
        return true;
    }

    public static boolean compareCharArrays(char[] array1, char[] array2) {
        if (array1.length != array2.length) {
            return false;
        }
        for (int index = 0; index < array1.length; index++) {
            if (array1[index] != array2[index]) {
                return false;
            }
        }
        return true;
    }

    /**
    * PUBLIC:
    *
    * Compare two vectors of types. Return true if the size of the vectors is the
    * same and each of the types in the first Vector are assignable from the types
    * in the corresponding objects in the second Vector.
    */
    public static boolean areTypesAssignable(List types1, List types2) {
        if ((types1 == null) || (types2 == null)) {
            return false;
        }

        if (types1.size() == types2.size()) {
            for (int i = 0; i < types1.size(); i++) {
                Class type1 = (Class)types1.get(i);
                Class type2 = (Class)types2.get(i);

                // if either are null then we assume assignability.
                if ((type1 != null) && (type2 != null)) {
                    if (!type1.isAssignableFrom(type2)) {
                        return false;
                    }
                }
            }
            return true;
        }

        return false;
    }

    /**
      * PUBLIC:
      * Compare the elements in 2 hashtables to see if they are equal
      *
      * Added Nov 9, 2000 JED Patch 2.5.1.8
      */
    public static boolean compareHashtables(Hashtable hashtable1, Hashtable hashtable2) {
        Enumeration enumtr;
        Object element;
        Hashtable clonedHashtable;

        if (hashtable1.size() != hashtable2.size()) {
            return false;
        }

        clonedHashtable = (Hashtable)hashtable2.clone();

        enumtr = hashtable1.elements();
        while (enumtr.hasMoreElements()) {
            element = enumtr.nextElement();
            if (clonedHashtable.remove(element) == null) {
                return false;
            }
        }

        return clonedHashtable.isEmpty();
    }

    /**
     * Compare two potential arrays and return true if they are the same. Will
     * check for BigDecimals as well.
     */
    public static boolean comparePotentialArrays(Object firstValue, Object secondValue) {
        Class firstClass = firstValue.getClass();
        Class secondClass = secondValue.getClass();

        // Arrays must be checked for equality because default does identity
        if ((firstClass == ClassConstants.APBYTE) && (secondClass == ClassConstants.APBYTE)) {
            return compareByteArrays((byte[])firstValue, (byte[])secondValue);
        } else if ((firstClass == ClassConstants.APCHAR) && (secondClass == ClassConstants.APCHAR)) {
            return compareCharArrays((char[])firstValue, (char[])secondValue);
        } else if ((firstClass.isArray()) && (secondClass.isArray())) {
            return compareArrays((Object[])firstValue, (Object[])secondValue);
        } else if (firstValue instanceof java.math.BigDecimal && secondValue instanceof java.math.BigDecimal) {
            // BigDecimals equals does not consider the precision correctly
            return compareBigDecimals((java.math.BigDecimal)firstValue, (java.math.BigDecimal)secondValue);
        }

        return false;
    }


    /**
     * Merge the two Maps into a new HashMap.
     */
    public static Map concatenateMaps(Map first, Map second) {
        Map concatenation = new HashMap(first.size() + second.size() + 4);

        concatenation.putAll(first);
        concatenation.putAll(second);

        return concatenation;
    }

    /**
      * Return a new vector with no duplicated values.
      */
    public static Vector concatenateUniqueVectors(Vector first, Vector second) {
        Vector concatenation;
        Object element;

        concatenation = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();

        for (Enumeration stream = first.elements(); stream.hasMoreElements();) {
            concatenation.addElement(stream.nextElement());
        }

        for (Enumeration stream = second.elements(); stream.hasMoreElements();) {
            element = stream.nextElement();
            if (!concatenation.contains(element)) {
                concatenation.addElement(element);
            }
        }

        return concatenation;

    }

    /**
      * Return a new List with no duplicated values.
      */
    public static List concatenateUniqueLists(List first, List second) {
        List concatenation = new ArrayList(first.size() + second.size());
        concatenation.addAll(first);

        for (Object element : second) {
            if (!concatenation.contains(element)) {
                concatenation.add(element);
            }
        }

        return concatenation;

    }

    public static Vector concatenateVectors(Vector first, Vector second) {
        Vector concatenation;

        concatenation = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();

        for (Enumeration stream = first.elements(); stream.hasMoreElements();) {
            concatenation.addElement(stream.nextElement());
        }

        for (Enumeration stream = second.elements(); stream.hasMoreElements();) {
            concatenation.addElement(stream.nextElement());
        }

        return concatenation;

    }

    /** Return a copy of the vector containing a subset starting at startIndex
     *  and ending at stopIndex.
     *  @param originalVector - original vector
     *  @param startIndex - starting position in vector
     *  @param stopIndex - ending position in vector
     *  @exception EclipseLinkException
     */
    public static Vector copyVector(List originalVector, int startIndex, int stopIndex) throws ValidationException {
        Vector newVector;

        if (stopIndex < startIndex) {
            return NonSynchronizedVector.newInstance();
        }

        newVector = NonSynchronizedVector.newInstance(stopIndex - startIndex);

        for (int index = startIndex; index < stopIndex; index++) {
            newVector.add(originalVector.get(index));
        }

        return newVector;
    }

    /**
     * Copy an array of strings to a new array
     * @param original
     * @return
     */
    public static String[] copyStringArray(String[] original){
        if (original == null){
            return null;
        }
        int length = original.length;
        String[] copy = new String[length];
        System.arraycopy(original, 0, copy, 0, length);
        return copy;
    }


    /**
     * Copy an array of int to a new array
     * @param original
     * @return
     */
    public static int[] copyIntArray(int[] original){
        if (original == null){
            return null;
        }
        int length = original.length;
        int[] copy = new int[length];
        System.arraycopy(original, 0, copy, 0, length);
        return copy;
    }

    /**
     * Return a string containing the platform-appropriate
     * characters for carriage return.
     */
    public static String cr() {
        if (CR == null) {
            CR = PrivilegedAccessHelper.getSystemProperty("line.separator");
        }
        return CR;
    }

    /**
     * Return the name of the "current working directory".
     */
    public static String currentWorkingDirectory() {
        // bug 2756643
        if (CURRENT_WORKING_DIRECTORY == null) {
            CURRENT_WORKING_DIRECTORY = PrivilegedAccessHelper.getSystemProperty("user.dir");
        }
        return CURRENT_WORKING_DIRECTORY;
    }

    /**
     * Return the name of the "temporary directory".
     */
    public static String tempDirectory() {
        // Bug 2756643
        if (TEMP_DIRECTORY == null) {
            TEMP_DIRECTORY = PrivilegedAccessHelper.getSystemProperty("java.io.tmpdir");
        }
        return TEMP_DIRECTORY;
    }

    /**
     * Answer a Date from a long
     *
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     * @param longObject - milliseconds from the epoch (00:00:00 GMT
     * Jan 1, 1970).  Negative values represent dates prior to the epoch.
     */
    public static java.sql.Date dateFromLong(Long longObject) {
        return new java.sql.Date(longObject);
    }

    /**
     * Answer a Date with the year, month, date.
     * This builds a date avoiding the deprecated, inefficient and concurrency bottleneck date constructors.
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     * The year, month, day are the values calendar uses,
     * i.e. year is from 0, month is 0-11, date is 1-31.
     */
    public static java.sql.Date dateFromYearMonthDate(int year, int month, int day) {
        // Use a calendar to compute the correct millis for the date.
        Calendar localCalendar = allocateCalendar();
        localCalendar.clear();
        localCalendar.set(year, month, day, 0, 0, 0);
        long millis = localCalendar.getTimeInMillis();
        java.sql.Date date = new java.sql.Date(millis);
        releaseCalendar(localCalendar);
        return date;
    }

    /**
     * Answer a Date from a string representation.
     * The string MUST be a valid date and in one of the following
     * formats: YYYY/MM/DD, YYYY-MM-DD, YY/MM/DD, YY-MM-DD.
     *
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     *
     * The Date class contains  some minor gotchas that you have to watch out for.
     * @param dateString - string representation of date
     * @return  - date representation of string
     */
    public static java.sql.Date dateFromString(String dateString) throws ConversionException {
        int year;
        int month;
        int day;
        StringTokenizer dateStringTokenizer;

        if (dateString.indexOf('/') != -1) {
            dateStringTokenizer = new StringTokenizer(dateString, "/");
        } else if (dateString.indexOf('-') != -1) {
            dateStringTokenizer = new StringTokenizer(dateString, "- ");
        } else {
            throw ConversionException.incorrectDateFormat(dateString);
        }

        try {
            year = Integer.parseInt(dateStringTokenizer.nextToken());
            month = Integer.parseInt(dateStringTokenizer.nextToken());
            day = Integer.parseInt(dateStringTokenizer.nextToken());
        } catch (NumberFormatException exception) {
            throw ConversionException.incorrectDateFormat(dateString);
        }

        // Java returns the month in terms of 0 - 11 instead of 1 - 12.
        month = month - 1;

        return dateFromYearMonthDate(year, month, day);
    }

    /**
     * Answer a Date from a timestamp
     *
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     * @param timestamp - timestamp representation of date
     * @return  - date representation of timestampObject
     */
    public static java.sql.Date dateFromTimestamp(java.sql.Timestamp timestamp) {
        return sqlDateFromUtilDate(timestamp);
    }

    /**
     * Returns true if the file of this name does indeed exist
     */
    public static boolean doesFileExist(String fileName) {
        FileReader reader = null;
        try {
            reader = new FileReader(fileName);
        } catch (FileNotFoundException fnfException) {
            return false;
        } finally {
        Helper.close(reader);
        }

        return true;
    }

    /**
     * Double up \ to allow printing of directories for source code generation.
     */
    public static String doubleSlashes(String path) {
        StringBuilder buffer = new StringBuilder(path.length() + 5);
        for (int index = 0; index < path.length(); index++) {
            char charater = path.charAt(index);
            buffer.append(charater);
            if (charater == '\\') {
                buffer.append('\\');
            }
        }

        return buffer.toString();
    }

    /**
     * Extracts the actual path to the jar file.
     */
    public static String extractJarNameFromURL(java.net.URL url) {
        String tempName = url.getFile();
        int start = tempName.indexOf("file:") + 5;
        int end = tempName.indexOf("!/");
        return tempName.substring(start, end);
    }

    /**
     * Return a string containing the platform-appropriate
     * characters for separating directory and file names.
     */
    public static String fileSeparator() {
        //Bug 2756643
        if (FILE_SEPARATOR == null) {
            FILE_SEPARATOR = PrivilegedAccessHelper.getSystemProperty("file.separator");
        }
        return FILE_SEPARATOR;
    }

    /**
     * INTERNAL:
     * Returns a Field for the specified Class and field name.
     * Uses Class.getDeclaredField(String) to find the field.
     * If the field is not found on the specified class
     * the superclass is checked, and so on, recursively.
     * Set accessible to true, so we can access private/package/protected fields.
     */
    public static Field getField(Class javaClass, String fieldName) throws NoSuchFieldException {
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
            try {
                return AccessController.doPrivileged(new PrivilegedGetField(javaClass, fieldName, true));
            } catch (PrivilegedActionException exception) {
                throw (NoSuchFieldException)exception.getException();
            }
        } else {
            return PrivilegedAccessHelper.getField(javaClass, fieldName, true);
        }
    }

    /**
     * INTERNAL:
     * Returns a Method for the specified Class, method name, and that has no
     * parameters. Uses Class.getDeclaredMethod(String Class[]) to find the
     * method. If the method is not found on the specified class the superclass
     * is checked, and so on, recursively. Set accessible to true, so we can
     * access private/package/protected methods.
     */
    public static Method getDeclaredMethod(Class javaClass, String methodName) throws NoSuchMethodException {
        return getDeclaredMethod(javaClass, methodName, null);
    }

    /**
     * INTERNAL:
     * Returns a Method for the specified Class, method name, and formal
     * parameter types. Uses Class.getDeclaredMethod(String Class[]) to find
     * the method. If the method is not found on the specified class the
     * superclass is checked, and so on, recursively. Set accessible to true,
     * so we can access private/package/protected methods.
     */
    public static Method getDeclaredMethod(Class javaClass, String methodName, Class[] methodParameterTypes) throws NoSuchMethodException {
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
            try {
                return AccessController.doPrivileged(
                    new PrivilegedGetMethod(javaClass, methodName, methodParameterTypes, true));
            }
            catch (PrivilegedActionException pae){
                if (pae.getCause() instanceof NoSuchMethodException){
                    throw (NoSuchMethodException)pae.getCause();
                }
                else {
                    // really shouldn't happen
                    throw (RuntimeException)pae.getCause();
                }
            }
        } else {
            return PrivilegedAccessHelper.getMethod(javaClass, methodName, methodParameterTypes, true);
        }
    }

    /**
     * Return the class instance from the class
     */
    public static Object getInstanceFromClass(Class classFullName) {
        if (classFullName == null) {
            return null;
        }

        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(classFullName));
                } catch (PrivilegedActionException exception) {
                    Exception throwableException = exception.getException();
                    if (throwableException instanceof InstantiationException) {
                        ValidationException exc = new ValidationException();
                        exc.setInternalException(throwableException);
                        throw exc;
                    } else {
                        ValidationException exc = new ValidationException();
                        exc.setInternalException(throwableException);
                        throw exc;
                    }
                }
            } else {
                return PrivilegedAccessHelper.newInstanceFromClass(classFullName);
            }
        } catch (InstantiationException notInstantiatedException) {
            ValidationException exception = new ValidationException();
            exception.setInternalException(notInstantiatedException);
            throw exception;
        } catch (IllegalAccessException notAccessedException) {
            ValidationException exception = new ValidationException();
            exception.setInternalException(notAccessedException);
            throw exception;
        }
    }

    /**
     *    Returns the object class. If a class is primitive return its non primitive class
     */
    public static Class getObjectClass(Class javaClass) {
        return ConversionManager.getObjectClass(javaClass);
    }

    /**
     *    Answers the unqualified class name for the provided class.
     */
    public static String getShortClassName(Class javaClass) {
        return getShortClassName(javaClass.getName());
    }

    /**
     *    Answers the unqualified class name from the specified String.
     */
    public static String getShortClassName(String javaClassName) {
        return javaClassName.substring(javaClassName.lastIndexOf('.') + 1);
    }

    /**
     *    Answers the unqualified class name for the specified object.
     */
    public static String getShortClassName(Object object) {
        return getShortClassName(object.getClass());
    }

    /**
     *    return a package name for the specified class.
     */
    public static String getPackageName(Class javaClass) {
        String className = Helper.getShortClassName(javaClass);
        return javaClass.getName().substring(0, (javaClass.getName().length() - (className.length() + 1)));
    }

    /**
     * Return a string containing the specified number of tabs.
     */
    public static String getTabs(int noOfTabs) {
        StringWriter writer = new StringWriter();
        for (int index = 0; index < noOfTabs; index++) {
            writer.write("\t");
        }
        return writer.toString();
    }

    /**
     * Returns the index of the the first <code>null</code> element found in the specified
     * <code>Vector</code> starting the search at the starting index specified.
     * Return  an int &gt;= 0 and less than size if a <code>null</code> element was found.
     * Return -1 if a <code>null</code> element was not found.
     * This is needed in jdk1.1, where <code>Vector.contains(Object)</code>
     * for a <code>null</code> element will result in a <code>NullPointerException</code>....
     */
    public static int indexOfNullElement(Vector v, int index) {
        int size = v.size();
        for (int i = index; i < size; i++) {
            if (v.elementAt(i) == null) {
                return i;
            }
        }
        return -1;
    }

    /**
     * ADVANCED
     * returns true if the class in question is a primitive wrapper
     */
    public static boolean isPrimitiveWrapper(Class classInQuestion) {
        return classInQuestion.equals(Character.class) || classInQuestion.equals(Boolean.class) || classInQuestion.equals(Byte.class) || classInQuestion.equals(Short.class) || classInQuestion.equals(Integer.class) || classInQuestion.equals(Long.class) || classInQuestion.equals(Float.class) || classInQuestion.equals(Double.class);
    }

    /**
     * Returns true if the string given is an all upper case string
     */
    public static boolean isUpperCaseString(String s) {
        char[] c = s.toCharArray();
        for (int i = 0; i < s.length(); i++) {
            if (Character.isLowerCase(c[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns true if the character given is a vowel. I.e. one of a,e,i,o,u,A,E,I,O,U.
     */
    public static boolean isVowel(char c) {
        return (c == 'A') || (c == 'a') || (c == 'e') || (c == 'E') || (c == 'i') || (c == 'I') || (c == 'o') || (c == 'O') || (c == 'u') || (c == 'U');
    }

    /**
     * Return an array of the files in the specified directory.
     * This allows us to simplify jdk1.1 code a bit.
     */
    public static File[] listFilesIn(File directory) {
        if (directory.isDirectory()) {
            return directory.listFiles();
        } else {
            return new File[0];
        }
    }

    /**
     * Make a Vector from the passed object.
     * If it's a Collection, iterate over the collection and add each item to the Vector.
     * If it's not a collection create a Vector and add the object to it.
     */
    public static Vector makeVectorFromObject(Object theObject) {
        if (theObject instanceof Vector) {
            return ((Vector)theObject);
        }
        if (theObject instanceof Collection) {
            Vector returnVector = new Vector(((Collection)theObject).size());
            Iterator iterator = ((Collection)theObject).iterator();
            while (iterator.hasNext()) {
                returnVector.add(iterator.next());
            }
            return returnVector;
        }

        Vector returnVector = new Vector();
        returnVector.addElement(theObject);
        return returnVector;
    }

    /**
     * Used by our byte code weaving to enable users who are debugging to output
     * the generated class to a file
     *
     * @param className
     * @param classBytes
     * @param outputPath
     */
    public static void outputClassFile(String className, byte[] classBytes,
            String outputPath) {
        StringBuilder directoryName = new StringBuilder();
        StringTokenizer tokenizer = new StringTokenizer(className, "\n\\/");
        String token = null;
        while (tokenizer.hasMoreTokens()) {
            token = tokenizer.nextToken();
            if (tokenizer.hasMoreTokens()) {
                directoryName.append(token + File.separator);
            }
        }
        FileOutputStream fos = null;
        try {
            String usedOutputPath = outputPath;
            if (!outputPath.endsWith(File.separator)) {
                usedOutputPath = outputPath + File.separator;
            }
            File file = new File(usedOutputPath + directoryName);
            if (!file.exists()) {
                if (!file.mkdirs()) {
                    AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.WEAVER,
                            "weaver_not_overwriting", file);
                }
            }
            file = new File(file, token + ".class");
            if (!file.exists()) {
                if (!file.createNewFile()) {
                    AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.WEAVER,
                            "weaver_not_overwriting", file);
                }
            } else {
                if (!PrivilegedAccessHelper.getSystemProperty(SystemProperties.WEAVING_SHOULD_OVERWRITE, "false").equalsIgnoreCase("true")) {
                    AbstractSessionLog.getLog().log(SessionLog.WARNING,
                            SessionLog.WEAVER, "weaver_not_overwriting",
                            className);
                    return;
                }
            }

            fos = new FileOutputStream(file);
            fos.write(classBytes);
        } catch (Exception e) {
            AbstractSessionLog.getLog().log(SessionLog.WARNING,
                    SessionLog.WEAVER, "weaver_could_not_write", className, e);
            AbstractSessionLog.getLog().logThrowable(SessionLog.FINEST,
                    SessionLog.WEAVER, e);
        } finally {
            Helper.close(fos);
        }
    }

    /**
     * Return a string containing the platform-appropriate
     * characters for separating entries in a path (e.g. the classpath)
     */
    public static String pathSeparator() {
        // Bug 2756643
        if (PATH_SEPARATOR == null) {
            PATH_SEPARATOR = PrivilegedAccessHelper.getSystemProperty("path.separator");
        }
        return PATH_SEPARATOR;
    }

    /**
     * Return a String containing the printed stacktrace of an exception.
     */
    public static String printStackTraceToString(Throwable aThrowable) {
        StringWriter swriter = new StringWriter();
        PrintWriter writer = new PrintWriter(swriter, true);
        aThrowable.printStackTrace(writer);
        writer.close();
        return swriter.toString();
    }

    /* Return a string representation of a number of milliseconds in terms of seconds, minutes, or
     * milliseconds, whichever is most appropriate.
     */
    public static String printTimeFromMilliseconds(long milliseconds) {
        if ((milliseconds > 1000) && (milliseconds < 60000)) {
            return (milliseconds / 1000) + "s";
        }
        if (milliseconds > 60000) {
            return (milliseconds / 60000) + "min " + printTimeFromMilliseconds(milliseconds % 60000);
        }
        return milliseconds + "ms";
    }

    /**
     * Given a Vector, print it, even if there is a null in it
     */
    public static String printVector(Vector vector) {
        StringWriter stringWriter = new StringWriter();
        stringWriter.write("[");
        Enumeration enumtr = vector.elements();
        stringWriter.write(String.valueOf(enumtr.nextElement()));
        while (enumtr.hasMoreElements()) {
            stringWriter.write(" ");
            stringWriter.write(String.valueOf(enumtr.nextElement()));
        }
        stringWriter.write("]");
        return stringWriter.toString();

    }

    public static Hashtable rehashHashtable(Hashtable table) {
        Hashtable rehashedTable = new Hashtable(table.size() + 2);

        Enumeration values = table.elements();
        for (Enumeration keys = table.keys(); keys.hasMoreElements();) {
            Object key = keys.nextElement();
            Object value = values.nextElement();
            rehashedTable.put(key, value);
        }

        return rehashedTable;
    }

    public static Map rehashMap(Map table) {
        HashMap rehashedTable = new HashMap(table.size() + 2);

        Iterator values = table.values().iterator();
        for (Iterator keys = table.keySet().iterator(); keys.hasNext();) {
            Object key = keys.next();
            Object value = values.next();
            rehashedTable.put(key, value);
        }

        return rehashedTable;
    }

    /**
     * Returns a String which has had enough non-alphanumeric characters removed to be equal to
     * the maximumStringLength.
     */
    public static String removeAllButAlphaNumericToFit(String s1, int maximumStringLength) {
        int s1Size = s1.length();
        if (s1Size <= maximumStringLength) {
            return s1;
        }

        // Remove the necessary number of characters
        StringBuilder buf = new StringBuilder();
        int numberOfCharsToBeRemoved = s1.length() - maximumStringLength;
        int s1Index = 0;
        while ((numberOfCharsToBeRemoved > 0) && (s1Index < s1Size)) {
            char currentChar = s1.charAt(s1Index);
            if (Character.isLetterOrDigit(currentChar)) {
                buf.append(currentChar);
            } else {
                numberOfCharsToBeRemoved--;
            }
            s1Index++;
        }

        // Append the rest of the character that were not parsed through.
        // Is it quicker to build a substring and append that?
        while (s1Index < s1Size) {
            buf.append(s1.charAt(s1Index));
            s1Index++;
        }

        //
        return buf.toString();
    }

    /**
     * Returns a String which has had enough of the specified character removed to be equal to
     * the maximumStringLength.
     */
    public static String removeCharacterToFit(String s1, char aChar, int maximumStringLength) {
        int s1Size = s1.length();
        if (s1Size <= maximumStringLength) {
            return s1;
        }

        // Remove the necessary number of characters
        StringBuilder buf = new StringBuilder();
        int numberOfCharsToBeRemoved = s1.length() - maximumStringLength;
        int s1Index = 0;
        while ((numberOfCharsToBeRemoved > 0) && (s1Index < s1Size)) {
            char currentChar = s1.charAt(s1Index);
            if (currentChar == aChar) {
                numberOfCharsToBeRemoved--;
            } else {
                buf.append(currentChar);
            }
            s1Index++;
        }

        // Append the rest of the character that were not parsed through.
        // Is it quicker to build a substring and append that?
        while (s1Index < s1Size) {
            buf.append(s1.charAt(s1Index));
            s1Index++;
        }

        //
        return buf.toString();
    }

    /**
     * Returns a String which has had enough of the specified character removed to be equal to
     * the maximumStringLength.
     */
    public static String removeVowels(String s1) {
        // Remove the vowels
        StringBuilder buf = new StringBuilder();
        int s1Size = s1.length();
        int s1Index = 0;
        while (s1Index < s1Size) {
            char currentChar = s1.charAt(s1Index);
            if (!isVowel(currentChar)) {
                buf.append(currentChar);
            }
            s1Index++;
        }

        //
        return buf.toString();
    }

    /**
     * Replaces the first subString of the source with the replacement.
     */
    public static String replaceFirstSubString(String source, String subString, String replacement) {
        int index = source.indexOf(subString);

        if (index >= 0) {
            return source.substring(0, index) + replacement + source.substring(index + subString.length());
        }
        return null;
    }

    public static Vector reverseVector(Vector theVector) {
        Vector tempVector = new Vector(theVector.size());
        Object currentElement;

        for (int i = theVector.size() - 1; i > -1; i--) {
            currentElement = theVector.elementAt(i);
            tempVector.addElement(currentElement);
        }

        return tempVector;
    }

    /**
     * Returns a new string with all space characters removed from the right
     *
     * @param originalString - timestamp representation of date
     * @return  - String
     */
    public static String rightTrimString(String originalString) {
        int len = originalString.length();
        while ((len > 0) && (originalString.charAt(len - 1) <= ' ')) {
            len--;
        }
        return originalString.substring(0, len);
    }

    /**
     * Returns a String which is a concatenation of two string which have had enough
     * vowels removed from them so that the sum of the sized of the two strings is less than
     * or equal to the specified size.
     */
    public static String shortenStringsByRemovingVowelsToFit(String s1, String s2, int maximumStringLength) {
        int size = s1.length() + s2.length();
        if (size <= maximumStringLength) {
            return s1 + s2;
        }

        // Remove the necessary number of characters
        int s1Size = s1.length();
        int s2Size = s2.length();
        StringBuilder buf1 = new StringBuilder();
        StringBuilder buf2 = new StringBuilder();
        int numberOfCharsToBeRemoved = size - maximumStringLength;
        int s1Index = 0;
        int s2Index = 0;
        int modulo2 = 0;

        // While we still want to remove characters, and not both string are done.
        while ((numberOfCharsToBeRemoved > 0) && !((s1Index >= s1Size) && (s2Index >= s2Size))) {
            if ((modulo2 % 2) == 0) {
                // Remove from s1
                if (s1Index < s1Size) {
                    if (isVowel(s1.charAt(s1Index))) {
                        numberOfCharsToBeRemoved--;
                    } else {
                        buf1.append(s1.charAt(s1Index));
                    }
                    s1Index++;
                }
            } else {
                // Remove from s2
                if (s2Index < s2Size) {
                    if (isVowel(s2.charAt(s2Index))) {
                        numberOfCharsToBeRemoved--;
                    } else {
                        buf2.append(s2.charAt(s2Index));
                    }
                    s2Index++;
                }
            }
            modulo2++;
        }

        // Append the rest of the character that were not parsed through.
        // Is it quicker to build a substring and append that?
        while (s1Index < s1Size) {
            buf1.append(s1.charAt(s1Index));
            s1Index++;
        }
        while (s2Index < s2Size) {
            buf2.append(s2.charAt(s2Index));
            s2Index++;
        }

        //
        return buf1.toString() + buf2.toString();
    }

    /**
     * Answer a sql.Date from a timestamp.
     */
    public static java.sql.Date sqlDateFromUtilDate(java.util.Date utilDate) {
        // PERF: Avoid deprecated get methods, that are now very inefficient.
        Calendar calendar = allocateCalendar();
        calendar.setTime(utilDate);
        java.sql.Date date = dateFromCalendar(calendar);
        releaseCalendar(calendar);
        return date;
    }

    /**
     * Print the sql.Date.
     */
    public static String printDate(java.sql.Date date) {
        // PERF: Avoid deprecated get methods, that are now very inefficient and used from toString.
        Calendar calendar = allocateCalendar();
        calendar.setTime(date);
        String string = printDate(calendar);
        releaseCalendar(calendar);
        return string;
    }

    /**
     * Print the date part of the calendar.
     */
    public static String printDate(Calendar calendar) {
        return printDate(calendar, true);
    }

    /**
     * Print the date part of the calendar.
     * Normally the calendar must be printed in the local time, but if the timezone is printed,
     * it must be printing in its timezone.
     */
    public static String printDate(Calendar calendar, boolean useLocalTime) {
        int year;
        int month;
        int day;
        if (useLocalTime && (!defaultTimeZone.equals(calendar.getTimeZone()))) {
            // Must convert the calendar to the local timezone if different, as dates have no timezone (always local).
            Calendar localCalendar = allocateCalendar();
            localCalendar.setTimeInMillis(calendar.getTimeInMillis());
            year = localCalendar.get(Calendar.YEAR);
            month = localCalendar.get(Calendar.MONTH) + 1;
            day = localCalendar.get(Calendar.DATE);
            releaseCalendar(localCalendar);
        } else {
            year = calendar.get(Calendar.YEAR);
            month = calendar.get(Calendar.MONTH) + 1;
            day = calendar.get(Calendar.DATE);
        }

        char[] buf = "2000-00-00".toCharArray();
        buf[0] = Character.forDigit(year / 1000, 10);
        buf[1] = Character.forDigit((year / 100) % 10, 10);
        buf[2] = Character.forDigit((year / 10) % 10, 10);
        buf[3] = Character.forDigit(year % 10, 10);
        buf[5] = Character.forDigit(month / 10, 10);
        buf[6] = Character.forDigit(month % 10, 10);
        buf[8] = Character.forDigit(day / 10, 10);
        buf[9] = Character.forDigit(day % 10, 10);

        return new String(buf);
    }

    /**
     * Print the sql.Time.
     */
    public static String printTime(java.sql.Time time) {
        // PERF: Avoid deprecated get methods, that are now very inefficient and used from toString.
        Calendar calendar = allocateCalendar();
        calendar.setTime(time);
        String string = printTime(calendar);
        releaseCalendar(calendar);
        return string;
    }

    /**
     * Print the time part of the calendar.
     */
    public static String printTime(Calendar calendar) {
        return printTime(calendar, true);
    }

    /**
     * Print the time part of the calendar.
     * Normally the calendar must be printed in the local time, but if the timezone is printed,
     * it must be printing in its timezone.
     */
    public static String printTime(Calendar calendar, boolean useLocalTime) {
        int hour;
        int minute;
        int second;
        if (useLocalTime && (!defaultTimeZone.equals(calendar.getTimeZone()))) {
            // Must convert the calendar to the local timezone if different, as dates have no timezone (always local).
            Calendar localCalendar = allocateCalendar();
            localCalendar.setTimeInMillis(calendar.getTimeInMillis());
            hour = localCalendar.get(Calendar.HOUR_OF_DAY);
            minute = localCalendar.get(Calendar.MINUTE);
            second = localCalendar.get(Calendar.SECOND);
            releaseCalendar(localCalendar);
        } else {
            hour = calendar.get(Calendar.HOUR_OF_DAY);
            minute = calendar.get(Calendar.MINUTE);
            second = calendar.get(Calendar.SECOND);
        }
        String hourString;
        String minuteString;
        String secondString;
        if (hour < 10) {
            hourString = "0" + hour;
        } else {
            hourString = Integer.toString(hour);
        }
        if (minute < 10) {
            minuteString = "0" + minute;
        } else {
            minuteString = Integer.toString(minute);
        }
        if (second < 10) {
            secondString = "0" + second;
        } else {
            secondString = Integer.toString(second);
        }
        return (hourString + ":" + minuteString + ":" + secondString);
    }

    /**
     * Print the Calendar.
     */
    public static String printCalendar(Calendar calendar) {
        return printCalendar(calendar, true);
    }

    /**
     * Print the Calendar.
     * Normally the calendar must be printed in the local time, but if the timezone is printed,
     * it must be printing in its timezone.
     */
    public static String printCalendar(Calendar calendar, boolean useLocalTime) {
        String millisString;

        //    String zeros = "000000000";
        if (calendar.get(Calendar.MILLISECOND) == 0) {
            millisString = "0";
        } else {
            millisString = buildZeroPrefixAndTruncTrailZeros(calendar.get(Calendar.MILLISECOND), 3);
        }

        StringBuilder timestampBuf = new StringBuilder();
        timestampBuf.append(printDate(calendar, useLocalTime));
        timestampBuf.append(" ");
        timestampBuf.append(printTime(calendar, useLocalTime));
        timestampBuf.append(".");
        timestampBuf.append(millisString);

        return timestampBuf.toString();
    }

    /**
     * Print the sql.Timestamp.
     */
    public static String printTimestamp(java.sql.Timestamp timestamp) {
        // PERF: Avoid deprecated get methods, that are now very inefficient and used from toString.
        Calendar calendar = allocateCalendar();
        calendar.setTime(timestamp);

        String nanosString;

        if (timestamp.getNanos() == 0) {
            nanosString = "0";
        } else {
            nanosString = buildZeroPrefixAndTruncTrailZeros(timestamp.getNanos(), 9);
        }

        StringBuilder timestampBuf = new StringBuilder();
        timestampBuf.append(printDate(calendar));
        timestampBuf.append(" ");
        timestampBuf.append(printTime(calendar));
        timestampBuf.append(".");
        timestampBuf.append(nanosString);

        releaseCalendar(calendar);

        return (timestampBuf.toString());
    }

    /**
     * Build a numerical string with leading 0s.  number is an existing number that
     * the new string will be built on.  totalDigits is the number of the required
     * digits of the string.
     */
    public static String buildZeroPrefix(int number, int totalDigits) {
        String numbString = buildZeroPrefixWithoutSign(number, totalDigits);

        if (number < 0) {
            numbString = "-" + numbString;
        } else {
            numbString = "+" + numbString;
        }
        return numbString;
    }

    /**
     * Build a numerical string with leading 0s.  number is an existing number that
     * the new string will be built on.  totalDigits is the number of the required
     * digits of the string.
     */
    public static String buildZeroPrefixWithoutSign(int number, int totalDigits) {
        String zeros = "000000000";
        int absValue = (number < 0) ? (-number) : number;
        String numbString = Integer.toString(absValue);

        // Add leading zeros
        numbString = zeros.substring(0, (totalDigits - numbString.length())) + numbString;

        return numbString;
    }

    /**
     * Build a numerical string with leading 0s and truncate trailing zeros.  number is
     * an existing number that the new string will be built on.  totalDigits is the number
     * of the required digits of the string.
     */
    public static String buildZeroPrefixAndTruncTrailZeros(int number, int totalDigits) {
        String zeros = "000000000";
        String numbString = Integer.toString(number);

        // Add leading zeros
        numbString = zeros.substring(0, (totalDigits - numbString.length())) + numbString;
        // Truncate trailing zeros
        char[] numbChar = new char[numbString.length()];
        numbString.getChars(0, numbString.length(), numbChar, 0);
        int truncIndex = totalDigits - 1;
        while (numbChar[truncIndex] == '0') {
            truncIndex--;
        }
        return new String(numbChar, 0, truncIndex + 1);
    }

    /**
     * Print the sql.Timestamp without the nanos portion.
     */
    public static String printTimestampWithoutNanos(java.sql.Timestamp timestamp) {
        // PERF: Avoid deprecated get methods, that are now very inefficient and used from toString.
        Calendar calendar = allocateCalendar();
        calendar.setTime(timestamp);
        String string = printCalendarWithoutNanos(calendar);
        releaseCalendar(calendar);
        return string;
    }

    /**
     * Print the Calendar without the nanos portion.
     */
    public static String printCalendarWithoutNanos(Calendar calendar) {
        StringBuilder timestampBuf = new StringBuilder();
        timestampBuf.append(printDate(calendar));
        timestampBuf.append(" ");
        timestampBuf.append(printTime(calendar));
        return timestampBuf.toString();
    }

    /**
     * Answer a sql.Date from a Calendar.
     */
    public static java.sql.Date dateFromCalendar(Calendar calendar) {
        if (!defaultTimeZone.equals(calendar.getTimeZone())) {
            // Must convert the calendar to the local timezone if different, as dates have no timezone (always local).
            Calendar localCalendar = allocateCalendar();
            localCalendar.setTimeInMillis(calendar.getTimeInMillis());
            java.sql.Date date = dateFromYearMonthDate(localCalendar.get(Calendar.YEAR), localCalendar.get(Calendar.MONTH), localCalendar.get(Calendar.DATE));
            releaseCalendar(localCalendar);
            return date;
        } else if ((calendar.get(Calendar.HOUR_OF_DAY) == 0)
                        && (calendar.get(Calendar.MINUTE) == 0)
                        && (calendar.get(Calendar.SECOND) == 0)
                        && (calendar.get(Calendar.MILLISECOND) == 0)) {
            // PERF: If just a date set in the Calendar, then just use its millis.
            return new java.sql.Date(calendar.getTimeInMillis());
        }
        return dateFromYearMonthDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE));
    }

    /**
     * Return a sql.Date with time component zeroed out.
     * Starting with version 12.1 Oracle jdbc Statement.setDate method no longer zeroes out the time component.
     */
    public static java.sql.Date truncateDate(java.sql.Date date) {
        // PERF: Avoid deprecated get methods, that are now very inefficient.
        Calendar calendar = allocateCalendar();
        calendar.setTime(date);
        if ((calendar.get(Calendar.HOUR_OF_DAY) != 0)
                || (calendar.get(Calendar.MINUTE) != 0)
                || (calendar.get(Calendar.SECOND) != 0)
                || (calendar.get(Calendar.MILLISECOND) != 0)) {
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH);
            int day = calendar.get(Calendar.DATE);
            calendar.clear();
            calendar.set(year, month, day, 0, 0, 0);
            long millis = calendar.getTimeInMillis();
            date = new java.sql.Date(millis);
        }
        releaseCalendar(calendar);
        return date;
    }

    /**
     * Return a sql.Date with time component zeroed out (with possible exception of milliseconds).
     * Starting with version 12.1 Oracle jdbc Statement.setDate method no longer zeroes out the whole time component,
     * yet it still zeroes out milliseconds.
     */
    public static java.sql.Date truncateDateIgnoreMilliseconds(java.sql.Date date) {
        // PERF: Avoid deprecated get methods, that are now very inefficient.
        Calendar calendar = allocateCalendar();
        calendar.setTime(date);
        if ((calendar.get(Calendar.HOUR_OF_DAY) != 0)
                || (calendar.get(Calendar.MINUTE) != 0)
                || (calendar.get(Calendar.SECOND) != 0)) {
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH);
            int day = calendar.get(Calendar.DATE);
            calendar.clear();
            calendar.set(year, month, day, 0, 0, 0);
            long millis = calendar.getTimeInMillis();
            date = new java.sql.Date(millis);
        }
        releaseCalendar(calendar);
        return date;
    }

    /**
     * Can be used to mark code if a workaround is added for a JDBC driver or other bug.
     */
    public static void systemBug(String description) {
        // Use sender to find what is needy.
    }

    /**
     * Answer a Time from a Date
     *
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     * @param date - time representation of date
     * @return  - time representation of dateObject
     */
    public static java.sql.Time timeFromDate(java.util.Date date) {
        // PERF: Avoid deprecated get methods, that are now very inefficient.
        Calendar calendar = allocateCalendar();
        calendar.setTime(date);
        java.sql.Time time = timeFromCalendar(calendar);
        releaseCalendar(calendar);
        return time;
    }

    /**
     * Answer a Time from a long
     *
     * @param longObject - milliseconds from the epoch (00:00:00 GMT
     * Jan 1, 1970).  Negative values represent dates prior to the epoch.
     */
    public static java.sql.Time timeFromLong(Long longObject) {
        return new java.sql.Time(longObject);
    }

    /**
     * Answer a Time with the hour, minute, second.
     * This builds a time avoiding the deprecated, inefficient and concurrency bottleneck date constructors.
     * The hour, minute, second are the values calendar uses,
     * i.e. year is from 0, month is 0-11, date is 1-31.
     */
    public static java.sql.Time timeFromHourMinuteSecond(int hour, int minute, int second) {
        // Use a calendar to compute the correct millis for the date.
        Calendar localCalendar = allocateCalendar();
        localCalendar.clear();
        localCalendar.set(1970, 0, 1, hour, minute, second);
        long millis = localCalendar.getTimeInMillis();
        java.sql.Time time = new java.sql.Time(millis);
        releaseCalendar(localCalendar);
        return time;
    }

    /**
     * Answer a Time from a string representation.
     * This method will accept times in the following
     * formats: HH-MM-SS, HH:MM:SS
     *
     * @param timeString - string representation of time
     * @return  - time representation of string
     */
    public static java.sql.Time timeFromString(String timeString) throws ConversionException {
        int hour;
        int minute;
        int second;
        String timePortion = timeString;

        if (timeString.length() > 12) {
            // Longer strings are Timestamp format (ie. Sybase & Oracle)
            timePortion = timeString.substring(11, 19);
        }

        if ((timePortion.indexOf('-') == -1) && (timePortion.indexOf('/') == -1) && (timePortion.indexOf('.') == -1) && (timePortion.indexOf(':') == -1)) {
            throw ConversionException.incorrectTimeFormat(timePortion);
        }
        StringTokenizer timeStringTokenizer = new StringTokenizer(timePortion, " /:.-");

        try {
            hour = Integer.parseInt(timeStringTokenizer.nextToken());
            minute = Integer.parseInt(timeStringTokenizer.nextToken());
            second = Integer.parseInt(timeStringTokenizer.nextToken());
        } catch (NumberFormatException exception) {
            throw ConversionException.incorrectTimeFormat(timeString);
        }

        return timeFromHourMinuteSecond(hour, minute, second);
    }

    /**
     * Answer a Time from a Timestamp
     * Usus the Hours, Minutes, Seconds instead of getTime() ms value.
     */
    public static java.sql.Time timeFromTimestamp(java.sql.Timestamp timestamp) {
        return timeFromDate(timestamp);
    }

    /**
     * Answer a sql.Time from a Calendar.
     */
    public static java.sql.Time timeFromCalendar(Calendar calendar) {
        if (!defaultTimeZone.equals(calendar.getTimeZone())) {
            // Must convert the calendar to the local timezone if different, as dates have no timezone (always local).
            Calendar localCalendar = allocateCalendar();
            localCalendar.setTimeInMillis(calendar.getTimeInMillis());
            java.sql.Time date = timeFromHourMinuteSecond(localCalendar.get(Calendar.HOUR_OF_DAY), localCalendar.get(Calendar.MINUTE), localCalendar.get(Calendar.SECOND));
            releaseCalendar(localCalendar);
            return date;
        }
        return timeFromHourMinuteSecond(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
    }

    /**
     * Answer a Timestamp from a Calendar.
     */
    public static java.sql.Timestamp timestampFromCalendar(Calendar calendar) {
        return timestampFromLong(calendar.getTimeInMillis());
    }

    /**
     * Answer a Timestamp from a java.util.Date.
     */
    public static java.sql.Timestamp timestampFromDate(java.util.Date date) {
        return timestampFromLong(date.getTime());
    }

    /**
     * Answer a Time from a long
     *
     * @param millis - milliseconds from the epoch (00:00:00 GMT
     * Jan 1, 1970).  Negative values represent dates prior to the epoch.
     */
    public static java.sql.Timestamp timestampFromLong(Long millis) {
        return timestampFromLong(millis.longValue());
    }

    /**
     * Answer a Time from a long
     *
     * @param millis - milliseconds from the epoch (00:00:00 GMT
     * Jan 1, 1970).  Negative values represent dates prior to the epoch.
     */
    public static java.sql.Timestamp timestampFromLong(long millis) {
        java.sql.Timestamp timestamp = new java.sql.Timestamp(millis);

        // P2.0.1.3: Didn't account for negative millis < 1970
        // Must account for the jdk millis bug where it does not set the nanos.
        if ((millis % 1000) > 0) {
            timestamp.setNanos((int)(millis % 1000) * 1000000);
        } else if ((millis % 1000) < 0) {
            timestamp.setNanos((int)(1000000000 - (Math.abs((millis % 1000) * 1000000))));
        }
        return timestamp;
    }

    /**
     * Answer a Timestamp from a string representation.
     * This method will accept strings in the following
     * formats: 
     * YYYY/MM/DD HH:MM:SS
     * YY/MM/DD HH:MM:SS
     * YYYY-MM-DD HH:MM:SS
     * YY-MM-DD HH:MM:SS
     * YYYY/MM/DD HH:MM:SS.NNNNNNN
     * YYYY/MM/DD HH:MM:SS.NNNNNNN+Z
     *
     * @param timestampString - string representation of timestamp
     * @return  - timestamp representation of string
     */
    public static java.sql.Timestamp timestampFromString(String timestampString) throws ConversionException {
        if ((timestampString.indexOf('-') == -1) && (timestampString.indexOf('/') == -1) && (timestampString.indexOf('.') == -1) && (timestampString.indexOf(':') == -1)) {
            throw ConversionException.incorrectTimestampFormat(timestampString);
        }
        StringTokenizer timestampStringTokenizer = new StringTokenizer(timestampString, " /:.-+");

        int year = 0, month = 0, day = 0;
        int hour = 0, minute = 0, second = 0, nanos = 0;
        try {
            year = Integer.parseInt(timestampStringTokenizer.nextToken());
            month = Integer.parseInt(timestampStringTokenizer.nextToken());
            day = Integer.parseInt(timestampStringTokenizer.nextToken());
            try {
                hour = Integer.parseInt(timestampStringTokenizer.nextToken());
                minute = Integer.parseInt(timestampStringTokenizer.nextToken());
                second = Integer.parseInt(timestampStringTokenizer.nextToken());
            } catch (java.util.NoSuchElementException endOfStringException) {
                // May be only a date string desired to be used as a timestamp.
            }
        } catch (NumberFormatException exception) {
            throw ConversionException.incorrectTimestampFormat(timestampString);
        }

        boolean containsNanos = timestampString.indexOf('.') > -1;
        if (containsNanos) {
            try {
                String nanoToken = timestampStringTokenizer.nextToken();
                nanos = Integer.parseInt(nanoToken);
                for (int times = 0; times < (9 - nanoToken.length()); times++) {
                    nanos = nanos * 10;
                }
            } catch (NumberFormatException exception) {
                throw ConversionException.incorrectTimestampFormat(timestampString);
            }
        }

        // Java returns the month in terms of 0 - 11 instead of 1 - 12.
        return timestampFromYearMonthDateHourMinuteSecondNanos(
            year, month - 1, day, hour, minute, second, nanos
        );
    }

    /**
     * Answer a Timestamp with the year, month, day, hour, minute, second.
     * The hour, minute, second are the values calendar uses,
     * i.e. year is from 0, month is 0-11, date is 1-31, time is 0-23/59.
     */
    @SuppressWarnings("deprecation")
    public static java.sql.Timestamp timestampFromYearMonthDateHourMinuteSecondNanos(int year, int month, int date, int hour, int minute, int second, int nanos) {
        // This was not converted to use Calendar for the conversion because calendars do not take nanos.
        // but it should be, and then just call setNanos.
        return new java.sql.Timestamp(year - 1900, month, date, hour, minute, second, nanos);
    }

    /**
     * Can be used to mark code as need if something strange is seen.
     */
    public static void toDo(String description) {
        // Use sender to find what is needy.
    }

    /**
     * Convert dotted format class name to slashed format class name.
     * @param dottedClassName
     * @return String
     */
    public static String toSlashedClassName(String dottedClassName){
        if(dottedClassName==null){
            return null;
        }else if(dottedClassName.indexOf('.')>=0){
           return dottedClassName.replace('.', '/');
        }else{
          return dottedClassName;
        }
    }

    /**
     * If the size of the original string is larger than the passed in size,
     * this method will remove the vowels from the original string.
     *
     * The removal starts backward from the end of original string, and stops if the
     * resulting string size is equal to the passed in size.
     *
     * If the resulting string is still larger than the passed in size after
     * removing all vowels, the end of the resulting string will be truncated.
     */
    public static String truncate(String originalString, int size) {
        if (originalString.length() <= size) {
            //no removal and truncation needed
            return originalString;
        }
        String vowels = "AaEeIiOoUu";
        StringBuilder newStringBufferTmp = new StringBuilder(originalString.length());

        //need to remove the extra characters
        int counter = originalString.length() - size;
        for (int index = (originalString.length() - 1); index >= 0; index--) {
            //search from the back to the front, if vowel found, do not append it to the resulting (temp) string!
            //i.e. if vowel not found, append the chararcter to the new string buffer.
            if (vowels.indexOf(originalString.charAt(index)) == -1) {
                newStringBufferTmp.append(originalString.charAt(index));
            } else {
                //vowel found! do NOT append it to the temp buffer, and decrease the counter
                counter--;
                if (counter == 0) {
                    //if the exceeded characters (counter) of vowel haven been removed, the total
                    //string size should be equal to the limits, so append the reversed remaining string
                    //to the new string, break the loop and return the shrunk string.
                    StringBuilder newStringBuffer = new StringBuilder(size);
                    newStringBuffer.append(originalString.substring(0, index));
                    //need to reverse the string
                    //bug fix: 3016423. append(BunfferString) is jdk1.4 version api. Use append(String) instead
                    //in order to support jdk1.3.
                    newStringBuffer.append(newStringBufferTmp.reverse().toString());
                    return newStringBuffer.toString();
                }
            }
        }

        //the shrunk string still too long, revrese the order back and truncate it!
        return newStringBufferTmp.reverse().toString().substring(0, size);
    }

    /**
     * Answer a Date from a long
     *
     * This implementation is based on the java.sql.Date class, not java.util.Date.
     * @param longObject - milliseconds from the epoch (00:00:00 GMT
     * Jan 1, 1970).  Negative values represent dates prior to the epoch.
     */
    public static java.util.Date utilDateFromLong(Long longObject) {
        return new java.util.Date(longObject);
    }

    /**
     * Answer a java.util.Date from a sql.date
     *
     * @param sqlDate - sql.date representation of date
     * @return  - java.util.Date representation of the sql.date
     */
    public static java.util.Date utilDateFromSQLDate(java.sql.Date sqlDate) {
        return new java.util.Date(sqlDate.getTime());
    }

    /**
     * Answer a java.util.Date from a sql.Time
     *
     * @param time - time representation of util date
     * @return  - java.util.Date representation of the time
     */
    public static java.util.Date utilDateFromTime(java.sql.Time time) {
        return new java.util.Date(time.getTime());
    }

    /**
     * Answer a java.util.Date from a timestamp
     *
     * @param timestampObject - timestamp representation of date
     * @return  - java.util.Date representation of timestampObject
     */
    public static java.util.Date utilDateFromTimestamp(java.sql.Timestamp timestampObject) {
        // Bug 2719624 - Conditionally remove workaround for java bug which truncated
        // nanoseconds from timestamp.getTime().  We will now only recalculate the nanoseconds
        // When timestamp.getTime() results in nanoseconds == 0;
        long time = timestampObject.getTime();
        boolean appendNanos = ((time % 1000) == 0);
        if (appendNanos) {
            return new java.util.Date(time + (timestampObject.getNanos() / 1000000));
        } else {
            return new java.util.Date(time);
        }
    }

    /**
     * Convert the specified array into a vector.
     */
    public static Vector vectorFromArray(Object[] array) {
        Vector result = new Vector(array.length);
        for (int i = 0; i < array.length; i++) {
            result.addElement(array[i]);
        }
        return result;
    }

    /**
     * Convert the byte array to a HEX string.
     * HEX allows for binary data to be printed.
     */
    public static void writeHexString(byte[] bytes, Writer writer) throws IOException {
        writer.write(buildHexStringFromBytes(bytes));
    }

    /**
     * Check if the value is 0 (int/long) for primitive ids.
     */
    public static boolean isEquivalentToNull(Object value) {
        return (!isZeroValidPrimaryKey
                    && (((value.getClass() == ClassConstants.LONG) && ((Long) value == 0L))
                            || ((value.getClass() == ClassConstants.INTEGER) && ((Integer) value == 0))));
    }

    /**
     * Returns true if the passed value is Number that is negative or equals to zero.
     */
    public static boolean isNumberNegativeOrZero(Object value) {
        return ((value.getClass() == ClassConstants.BIGDECIMAL) && (((BigDecimal)value).signum() <= 0)) ||
                ((value.getClass() == ClassConstants.BIGINTEGER) && (((BigInteger)value).signum() <= 0)) ||
                ((value instanceof Number) && (((Number)value).longValue() <= 0));
    }

    /**
     * Return an integer representing the number of occurrences (using equals()) of the
     * specified object in the specified list.
     * If the list is null or empty (or both the object and the list is null), 0 is returned.
     */
    public static int countOccurrencesOf(Object comparisonObject, List list) {
        int instances = 0;
        boolean comparisonObjectIsNull = comparisonObject == null;
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                Object listObject = list.get(i);
                if ((comparisonObjectIsNull && listObject == null) || (!comparisonObjectIsNull && comparisonObject.equals(listObject))) {
                    instances++;
                }
            }
        }
        return instances;
    }

    /**
     * Convert the URL into a URI allowing for special chars.
     */
    public static URI toURI(java.net.URL url) throws URISyntaxException {
        try {
            // Attempt to use url.toURI since it will deal with all urls
            // without special characters and URISyntaxException allows us
            // to catch issues with special characters. This will handle
            // URLs that already have special characters replaced such as
            // URLS derived from searches for persistence.xml on the Java
            // System class loader
            return url.toURI();
        } catch (URISyntaxException exception) {
            // Use multi-argument constructor for URI since single-argument
            // constructor and URL.toURI() do not deal with special
            // characters in path
            return new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), null);
        }
    }

    /**
     * Return the get method name weaved for a value-holder attribute.
     */
    public static String getWeavedValueHolderGetMethodName(String attributeName) {
        return PERSISTENCE_GET + attributeName + "_vh";
    }

    /**
     * Return the set method name weaved for a value-holder attribute.
     */
    public static String getWeavedValueHolderSetMethodName(String attributeName) {
        return PERSISTENCE_SET + attributeName + "_vh";
    }

    /**
     * Return the set method name weaved for getting attribute value.
     * This method is always weaved in field access case.
     * In property access case the method weaved only if attribute name is the same as property name:
     * for instance, the method weaved for "manager" attribute that uses "getManager" / "setManager" access methods,
     * but not for "m_address" attribute that uses "getAddress" / "setAddress" access methods.
     */
    public static String getWeavedGetMethodName(String attributeName) {
        return PERSISTENCE_GET + attributeName;
    }

    /**
     * Return the set method name weaved for setting attribute value.
     * This method is always weaved in field access case.
     * In property access case the method weaved only if attribute name is the same as property name:
     * for instance, the method weaved for "manager" attribute that uses "getManager" / "setManager" access methods,
     * but not for "m_address" attribute that uses "getAddress" / "setAddress" access methods.
     */
    public static String getWeavedSetMethodName(String attributeName) {
        return PERSISTENCE_SET + attributeName;
    }

    /**
     * Close a closeable object, eating the exception
     */
    public static void close(Closeable c) {
        try {
            if (c != null) {
                c.close();
            }
        } catch (IOException exception) {
        }
    }

    /**
     * INTERNAL:
     * Method to convert a getXyz or isXyz method name to an xyz attribute name.
     * NOTE: The method name passed it may not actually be a method name, so
     * by default return the name passed in.
     */
    public static String getAttributeNameFromMethodName(String methodName) {
        String restOfName = methodName;

        // We're looking at method named 'get' or 'set', therefore,
        // there is no attribute name, set it to "" string for now.
        if (methodName.equals(GET_PROPERTY_METHOD_PREFIX) || methodName.equals(IS_PROPERTY_METHOD_PREFIX)) {
            return "";
        } else if (methodName.startsWith(GET_PROPERTY_METHOD_PREFIX)) {
            restOfName = methodName.substring(POSITION_AFTER_GET_PREFIX);
        } else if (methodName.startsWith(IS_PROPERTY_METHOD_PREFIX)){
            restOfName = methodName.substring(POSITION_AFTER_IS_PREFIX);
        }
        //added for bug 234222 - property name generation differs from Introspector.decapitalize
        return java.beans.Introspector.decapitalize(restOfName);
    }

    public static String getDefaultStartDatabaseDelimiter(){
        if (defaultStartDatabaseDelimiter == null){
            defaultStartDatabaseDelimiter = DEFAULT_DATABASE_DELIMITER;
        }
        return defaultStartDatabaseDelimiter;
    }

    public static String getDefaultEndDatabaseDelimiter(){
        if (defaultEndDatabaseDelimiter == null){
            defaultEndDatabaseDelimiter = DEFAULT_DATABASE_DELIMITER;
        }
        return defaultEndDatabaseDelimiter;
    }

    public static void setDefaultStartDatabaseDelimiter(String delimiter){
        defaultStartDatabaseDelimiter = delimiter;
    }

    public static void setDefaultEndDatabaseDelimiter(String delimiter){
        defaultEndDatabaseDelimiter = delimiter;
    }

    /**
     * Convert the SQL like pattern to a regex pattern.
     */
    public static String convertLikeToRegex(String like) {
        // Bug 3936427 - Replace regular expression reserved characters with escaped version of those characters
        // For instance replace ? with \?
        String pattern = like.replaceAll("\\?", "\\\\?");
        pattern = pattern.replaceAll("\\*", "\\\\*");
        pattern = pattern.replaceAll("\\.", "\\\\.");
        pattern = pattern.replaceAll("\\[", "\\\\[");
        pattern = pattern.replaceAll("\\)", "\\\\)");
        pattern = pattern.replaceAll("\\(", "\\\\(");
        pattern = pattern.replaceAll("\\{", "\\\\{");
        pattern = pattern.replaceAll("\\+", "\\\\+");
        pattern = pattern.replaceAll("\\^", "\\\\^");
        pattern = pattern.replaceAll("\\|", "\\\\|");

        // regular expressions to substitute SQL wildcards with regex wildcards

        // Use look behind operators to replace "%" which is not preceded by "\" with ".*"
        pattern = pattern.replaceAll("(?<!\\\\)%", ".*");

        // Use look behind operators to replace "_" which is not preceded by "\" with "."
        pattern = pattern.replaceAll("(?<!\\\\)_", ".");

        // replace "\%" with "%"
        pattern = pattern.replaceAll("\\\\%", "%");

        // replace "\_" with "_"
        pattern = pattern.replaceAll("\\\\_", "_");
        // regex requires ^ and $ if pattern must start at start and end at end of string as like requires.
        pattern = "^" + pattern + "$";
        return pattern;
    }

    public static boolean isLob(DatabaseField field) {
        int sqlType = field.sqlType;
        if (sqlType == DatabaseField.NULL_SQL_TYPE) {
            Class type = field.getType();
            if (type != null) {
                return ClassConstants.BLOB.equals(type) || ClassConstants.CLOB.equals(type);
            } else {
                return false;
            }
        } else {
            return DatabaseAccessor.isBlob(sqlType) || DatabaseAccessor.isClob(sqlType);
        }
    }

    public static boolean hasLob(Collection<DatabaseField> fields) {
        for (DatabaseField field : fields) {
            if (isLob(field)) {
                return true;
            }
        }
        return false;
    }

    public static long timeWithRoundMiliseconds() {
        return new Date().getTime() / 1000 * 1000;
    }
}
