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