image
 
image
Util.java


/*::.
==================================================================================================================================
=================================================¦ Copyright © 2007 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       Util.java
Originator: Allen Baker (2007.05.27 12:32)
LayoutRev:  5
================================================================================================================================== */



/*.
==========================================================================================
Package
------------------------------------------------------------------------------------------ */
package cosmicabyss.com.lib;



/*.
==========================================================================================
Imports
------------------------------------------------------------------------------------------ */
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import java.text.*;
import java.sql.*;
import java.security.*;



/*::
======================================================================================================================== *//**
This class is an implementation of the Utility pattern. Calling it a pattern is a way of legitimizing what is just a
collection of a whole bunch of stuff that doesn't really belong together. Here's how the Utility pattern is
characterized:
   <BLOCKQUOTE>
      The Utility pattern is a software pattern that is used for utility classes that do not require instantiation and
      only have static methods. It is a stateless class and so no instance can be created. Good candidates for utility
      classes are convenience methods that can be grouped together functionally.
   </BLOCKQUOTE>

All the methods in this class are static and instantiating a Utility class object would be pointless. The methods are
simply used in accordance with the procedural programming paradigm and there is nothing object oriented about them.<P>

This class is essentially a collection of miscellaneous methods. They are gathered together in this Utility class
because they are generally unrelated to each other or are related to only a very small number of others. They are all
static and therefor they don't require persistent state data which is a prime driver of the need for a "real" class.
Furthermore, no substantial subset of them is cohesive enough to justify cluttering the class library namespace by
grouping them together into a real class. With that said, there is a lot of very useful functionality in this class.

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  no example provided
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="Util.java.html">
               Util.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class Util
   {



   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Initialization  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   static
      {
//      /*.
//      ==========================================================================================
//      Make sure all the class constants and variables are initialized the first time the JVM
//      loads this class code and before anything else in this class is accessed
//      ------------------------------------------------------------------------------------------ */
//      initializeClassConstantsAndVariables();
      /*.
      ==========================================================================================
      Adds the BouncyCastle provider to the next position available. This statement is in lieu
      of configuring the BouncyCastle provider into the Java environment according to the
      following procedure:

         The provider can also be configured as part of your environment via static registration
         by adding an entry to the java.security properties file:

            (found in $JAVA_HOME/jre/lib/security/java.security, where $JAVA_HOME is the
            location of your JDK/JRE distribution).

         You'll find detailed instructions in the file but basically it comes down to adding a
         line:

            Security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider

         Where <n> is the preference you want the provider at (1 being the most prefered).
      ------------------------------------------------------------------------------------------ */
//      Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
      }



   /*:.
   ==============================================================================================================
   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[  Methods  ]>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Protected  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Private  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*.
   ==========================================================================================
   Class Constants
      CLASS_NAME:
         The name of this class
      DFLT_LINE_LEN:
         The default line length for word wrapping
   ------------------------------------------------------------------------------------------ */
   private static final XString  CLASS_NAME    = new XString(Util.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();
   /*.
   ==========================================================================================
   Class variables
      cOut : console output.
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cOut = ConsoleStream.getSingleton();



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Inner Classes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Public Static Methods  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */


   /*:                                    :METHOD:000:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method reverses the order of the elements of an ArrayList.

   <P><B>Implementation: </B><A HREF="Util.java.html#000">View source</A>

   @return
      This method returns a reversed copy of the input ArrayList.

   @param
      pArrayList is the ArrayList to reverse.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> ArrayList<Type1> reversedArrayList(ArrayList<Type1> pArrayList)
      {
      cosmicabyss.com.lib.Stack<Type1>  stk  = new cosmicabyss.com.lib.Stack<Type1>();
      for (Type1  element  :  pArrayList)
         {
         stk.push(element);
         }
      ArrayList<Type1>  ary = new ArrayList<Type1>();
      while (stk.size()>0)
         {
         ary.add(stk.pop());
         }
      return ary;
      }



   /*:                                    :METHOD:001:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sorts the elements of an ArrayList.

   <P><B>Implementation: </B><A HREF="Util.java.html#001">View source</A>

   @return
      This method returns a sorted copy of the input ArrayList.

   @param
      pArray is the ArrayList to sort.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> ArrayList<Type1> sortedArrayList(ArrayList<Type1> pArrayList)
      {
      return sortedArray(pArrayList);
      }



   /*:                                    :METHOD:002:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sorts the elements of an ArrayList or array. This thing cannot be genercized.

   Since Java won't allow this (generic array creation) ...
      <BLOCKQUOTE>
         <PRE id="unindent">
            Type1[] array = new Type1[pArray.length];
            System.copyArray(pArray,0,array,array.length);
            Arrays.sort(array);
         </PRE>
      </BLOCKQUOTE>
    We have to simulate it using this klunky method.

   <P><B>Implementation: </B><A HREF="Util.java.html#002">View source</A>

   @return
      This method returns a sorted copy of the input array.

   @param
      pArray is the array to sort.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   @SuppressWarnings("unchecked")
   public static <Type1> Type1 sortedArray(Type1 pArray)
      {
      /*.
      ==========================================================================================
      A ArrayList
      ------------------------------------------------------------------------------------------ */
      if (pArray instanceof ArrayList)
         {
         ArrayList  lame  = (ArrayList)pArray;
         Object[]   array = lame.toArray();
         Arrays.sort(array);
         return (Type1)(new ArrayList<Object>(Arrays.asList(array)));
         }
      /*.
      ==========================================================================================
      A byte[]
      ------------------------------------------------------------------------------------------ */
      if (pArray instanceof byte[])
         {
         byte[]  lame  = (byte[])pArray;
         byte[]  array = new byte[lame.length];
         System.arraycopy(lame,0,array,0,array.length);
         Arrays.sort(array);
         return (Type1)array;
         }
      /*.
      ==========================================================================================
      An int[]
      ------------------------------------------------------------------------------------------ */
      else if (pArray instanceof int[])
         {
         int[]  lame  = (int[])pArray;
         int[]  array = new int[lame.length];
         System.arraycopy(lame,0,array,0,array.length);
         Arrays.sort(array);
         return (Type1)array;
         }
      /*.
      ==========================================================================================
      And we can add others - double[], String[], TunaFishCasserole[], etc..
      ------------------------------------------------------------------------------------------ */
      /*.
      ==========================================================================================
      Houston, we have a problem.
      ------------------------------------------------------------------------------------------ */
      else
         {
         return pArray;
         }
      }



   /*:                                    :METHOD:003:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method randonmizes the order of the elements of an ArrayList.

   <P><B>Implementation: </B><A HREF="Util.java.html#003">View source</A>

   @return
      This method returns a randomized copy of the input array.

   @param
      pArray is the array to randomize.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> ArrayList<Type1> shuffledArrayList(ArrayList<Type1> pArrayList)
      {
      return shuffledArray(pArrayList,new XRandom());
      }



   /*:                                    :METHOD:004:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method randomizes the elements of an ArrayList or array. This thing cannot be genercized.

   Since Java won't allow this (generic array creation) ...
      <BLOCKQUOTE>
         <PRE id="unindent">
            Type1[] array = new Type1[pArray.length];
            System.copyArray(pArray,0,array,array.length);
            Arrays.randomize(array);
         </PRE>
      </BLOCKQUOTE>
    We have to simulate it using this klunky method.

   <P><B>Implementation: </B><A HREF="Util.java.html#004">View source</A>

   @return
      This method returns a randomized copy of the input array.

   @param
      pArray is the array to randomize.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   @SuppressWarnings("unchecked")
   public static <Type1> Type1 shuffledArray(Type1 pArray, XRandom pRandomizer)
      {
      /*.
      ==========================================================================================
      An ArrayList
      ------------------------------------------------------------------------------------------ */
      if (pArray instanceof ArrayList)
         {
         ArrayList  lame = (ArrayList)pArray;
         if (lame.size() < 2)
            {
            return pArray;
            }
         Object[]  array = lame.toArray();
         for (int i=0; i<(array.length); i++)
            {
            int  j;
            int  k;
            do
               {
               j = pRandomizer.nextInt(array.length);
               k = pRandomizer.nextInt(array.length);
               } while (j == k);
            Object  temp = array[j];
            array[j] = array[k];
            array[k] = temp;
            }
         return (Type1)(new ArrayList<Object>(Arrays.asList(array)));
         }
      /*.
      ==========================================================================================
      A byte[]
      ------------------------------------------------------------------------------------------ */
      if (pArray instanceof byte[])
         {
         byte[]  lame  = (byte[])pArray;
         if (lame.length < 2)
            {
            return pArray;
            }
         byte[]  array = new byte[lame.length];
         System.arraycopy(lame,0,array,0,array.length);
         for (int i=0; i<(array.length); i++)
            {
            int  j;
            int  k;
            do
               {
               j = pRandomizer.nextInt(array.length);
               k = pRandomizer.nextInt(array.length);
               } while (j == k);
            byte  temp = array[j];
            array[j] = array[k];
            array[k] = temp;
            }
         return (Type1)array;
         }
      /*.
      ==========================================================================================
      An int[]
      ------------------------------------------------------------------------------------------ */
      else if (pArray instanceof int[])
         {
         int[]  lame  = (int[])pArray;
         if (lame.length < 2)
            {
            return pArray;
            }
         int[]  array = new int[lame.length];
         System.arraycopy(lame,0,array,0,array.length);
         for (int i=0; i<(array.length); i++)
            {
            int  j;
            int  k;
            do
               {
               j = pRandomizer.nextInt(array.length);
               k = pRandomizer.nextInt(array.length);
               } while (j == k);
            int  temp = array[j];
            array[j] = array[k];
            array[k] = temp;
            }
         return (Type1)array;
         }
      /*.
      ==========================================================================================
      And we can add others - double[], String[], TunaFishCasserole[], etc..
      ------------------------------------------------------------------------------------------ */
      /*.
      ==========================================================================================
      Houston, we have a problem.
      ------------------------------------------------------------------------------------------ */
      else
         {
         return pArray;
         }
      }



   /*:                                    :METHOD:005:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a XString representation of the current system date-time in this format: yyyy-MM-dd
   HH:mm:ss.SSS000000.

   <P><B>Implementation: </B><A HREF="Util.java.html#005">View source</A>

   @return
      A XString representation of the date-time in this format: yyyy-MM-dd HH:mm:ss.SSS000000.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static XString timeStamp()
      {
      return timeStamp(new java.util.Date());
      }



   /*:                                    :METHOD:006:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a XString representation of the current system date-time in the specified format.

   <P><B>Implementation: </B><A HREF="Util.java.html#006">View source</A>

   @return
      A XString representation of the date-time in the specified format.

   @param
      pFormat is the SimpleDateFormat string that controls how the specified date will be formatted.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString timeStamp(Type1 pFormat)
      {
      XString  fmt = XString.toXString(pFormat);
      return timeStamp(fmt.string(), new java.util.Date());
      }



   /*:                                    :METHOD:007:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a XString representation of the specified date-time in this format: yyyy-MM-dd
   HH:mm:ss.SSS000000.

   <P><B>Implementation: </B><A HREF="Util.java.html#007">View source</A>

   @return
      A XString representation of the date-time in this format: yyyy-MM-dd HH:mm:ss.SSS000000.

   @param
      pDate is the specified date to get a String representation of
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static XString timeStamp(java.util.Date pDate)
      {
      return timeStamp("yyyy-MM-dd HH:mm:ss.SSS000000",pDate);
      }



   /*:                                    :METHOD:008:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a XString representation of the specified date-time in the specified format.

   <P><B>Implementation: </B><A HREF="Util.java.html#008">View source</A>

   @return
      A XString representation of the date-time formatted according to the specified format string

   @param
      pFormat is the SimpleDateFormat string that controls how the specified date will be formatted.
   @param
      pDate is the specified date to get a XString representation of
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString timeStamp(Type1 pFormat, java.util.Date pDate)
      {
      XString           fmt       = XString.toXString(pFormat);
      SimpleDateFormat  formatter = new SimpleDateFormat(fmt.string());
      return new XString(formatter.format(pDate));
      }



   /*:                                    :METHOD:009:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a date object for a specific date.

   <P><B>Implementation: </B><A HREF="Util.java.html#009">View source</A>

   @return
      A date object initialized to the specified date

   @param
      Year is the year component of the date
   @param
      Month is the month-of-the-year component of the date
   @param
      Day is the day-of-the-month component of the date
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static java.util.Date getDate(int year, int month, int day)
      {
      GregorianCalendar cal = new GregorianCalendar(year,month,day,0,0,0);
      return cal.getTime();
      }



   /*:                                    :METHOD:010:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates and returns a list of strings each containing a date in this format:
      Yyyy.mm.dd

   The first date and the last date to put into the list are given as parameters. This method will
   generate all intervening dates between the first and last date and add them in order to the list.

   <P><B>Implementation: </B><A HREF="Util.java.html#010">View source</A>

   @return
      An ArrayList of XStrings, each containing a date

   @param
      pFirstDate contains a string representation of the first date to put into the date list. This
      parameter must be formatted like: yyyy.mm.dd

   @param
      pLastDate contains a string representation of the last date to put into the date list. This
      parameter must be formatted like: yyyy.mm.dd
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ArrayList<XString> dateList(XString pFirstDate, XString pLastDate) throws Exception
      {
      ArrayList<XString>  theDateList = new ArrayList<XString>();
      /*.
      ==========================================================================================
      If the first date is greater than the last date, then we're going to count up from the
      first date to the last date. If it is less than, then we're going to count down from the
      first date to the last date.
      ------------------------------------------------------------------------------------------ */
      int  increment = (pFirstDate.compareTo(pLastDate) <= 0)? (1) : (-1);
      /*.
      ==========================================================================================
      We'll use nextDate to do the date incrementation so we don't have to keep track of the
      number of days per month etc. Ourselves.
      ------------------------------------------------------------------------------------------ */
      ArrayList<XString>  firstDateTokens = pFirstDate.tokenizedString(".");
      GregorianCalendar   nextDate = new GregorianCalendar
         (
         UMath.decodeDecimalInt(firstDateTokens.get(0)),
         UMath.decodeDecimalInt(firstDateTokens.get(1)) - 1,  // java lamely uses 0-based month numbers; the rest of world including me uses 1-based
         UMath.decodeDecimalInt(firstDateTokens.get(2))
         );
      /*.
      ==========================================================================================
      Load the date list with each sequential date until the last date has been loaded
      ------------------------------------------------------------------------------------------ */
      while (true)
         {
         XString  thisDate = Util.timeStamp("yyyy.MM.dd",nextDate.getTime());
         theDateList.add(thisDate);
         nextDate.add(Calendar.DAY_OF_YEAR,increment);
         if (thisDate.equals(pLastDate)) break;
         }
      return theDateList;
      }



   /*:                                    :METHOD:011:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Get a date object for a specific date.

   <P><B>Implementation: </B><A HREF="Util.java.html#011">View source</A>

   @return
      A date object initialized to the specified date

   @param
      Year is the year component of the date
   @param
      Month is the month-of-the-year component of the date
   @param
      Day is the day-of-the-month component of the date
   @param
      Hour is the hour-of-the-day component of the date
   @param
      Minute is the minute-of-the-hour component of the date
   @param
      Second is the second-of-the-minute component of the date
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static java.util.Date getDate(int year, int month, int day, int hour, int minute, int second)
      {
      GregorianCalendar cal = new GregorianCalendar(year,month,day,hour,minute,second);
      return cal.getTime();
      }



   /*:                                    :METHOD:012:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns a java.util.Date object from an ArrayList<XString> of date components. The date
   components are XString representations of the year, month, day, hour, minute, and second of the
   date.

   <P><B>Implementation: </B><A HREF="Util.java.html#012">View source</A>

   @return
      A java.util.Date object representation of the date described by the ArrayList<XString> of date
      components.

   @param
      pComponents is an ArrayList<Integer> containing the components in XString form as follows:
         <BLOCKQUOTE>
            <PRE id="unindent">
               ArrayList<XString>[0] = the years   component in the yyyy form
               ArrayList<XString>[1] = the months  component in the MM form
               ArrayList<XString>[2] = the days    component in the dd form
               ArrayList<XString>[3] = the hours   component in the HH (24hr) form
               ArrayList<XString>[4] = the minutes component in the mm form
               ArrayList<XString>[5] = the seconds component in the ss form
            </PRE>
         </BLOCKQUOTE>
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static java.util.Date getDateFromComponents(ArrayList<XString> pComponents) throws Exception
      {
      return Util.getDate
         (
         UMath.decodeDecimalInt(pComponents.get(0)), // yyyy
         UMath.decodeDecimalInt(pComponents.get(1)), // MM
         UMath.decodeDecimalInt(pComponents.get(2)), // dd
         UMath.decodeDecimalInt(pComponents.get(3)), // HH
         UMath.decodeDecimalInt(pComponents.get(4)), // mm
         UMath.decodeDecimalInt(pComponents.get(5))  // ss
         );
      }



   /*:                                    :METHOD:013:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method computes the difference in milliseconds between two dates. It computes the difference as
   pLaterDate - pEarlierDate.

   <P><B>Implementation: </B><A HREF="Util.java.html#013">View source</A>

   @return
      A long containing the difference in milliseconds between pEarlierDate and pLaterDate.

   @param
      pEarlierDate is the first date
   @param
      pLaterDate is the second date
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static long getDateDifferenceTime(java.util.Date pEarlierDate, java.util.Date pLaterDate)
      {
      long  earlier = pEarlierDate.getTime();
      long  later   = pLaterDate.getTime();
      return (later - earlier);
      }



   /*:                                    :METHOD:014:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method computes the difference in components between two dates. It computes the difference as
   pLaterDate - pEarlierDate. The components are the difference in years, months, days, hours, minutes,
   and seconds.

   <P><B>Implementation: </B><A HREF="Util.java.html#014">View source</A>

   @return
      An ArrayList<Integer> containing the difference in components between pEarlierDate and
      pLaterDate.
         <BLOCKQUOTE>
            <PRE id="unindent">
               ArrayList<Integer>[0] = the years   component of the difference.
               ArrayList<Integer>[1] = the months  component of the difference.
               ArrayList<Integer>[2] = the days    component of the difference.
               ArrayList<Integer>[3] = the hours   component of the difference.
               ArrayList<Integer>[4] = the minutes component of the difference.
               ArrayList<Integer>[5] = the seconds component of the difference.
            </PRE>
         </BLOCKQUOTE>

   @param
      pEarlierDate is the first date
   @param
      pLaterDate is the second date
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ArrayList<Integer> getDateDifferenceComponents(java.util.Date pEarlierDate, java.util.Date pLaterDate)
      {
      ArrayList<Integer> result = new ArrayList<Integer>();
      long               delta  = getDateDifferenceTime(pEarlierDate,pLaterDate);
      /*.
      ==========================================================================================
      There are 365.2425 days in a year and therefor, there are 30.436875 days in a month. To
      compute the number of months there are in the number of milliseconds that are returned by
      getDateDifferenceTime() without having to use floating point arithmetic, we will scale up
      the number of milliseconds by 1,000,000 so that we can divide the resulting number by
      30436875 instead of 30.436875. When we have divided out the number of months, we will
      scale the number back down by dividing it by the 1,000,000. Then we will continue with our
      component arithmetic on the scaled down nmber.

      Here's the logic in a more compact and readable form:
         <BLOCKQUOTE>
            <PRE id="unindent">
               long  yy = delta/(1000L*60L*60L*24L*30436875L*12); delta = delta%(1000L*60L*60L*24L*30436875L*12);
               long  MM = delta/(1000L*60L*60L*24L*30436875L);    delta = delta%(1000L*60L*60L*24L*30436875L);     delta = delta/1000000;
               long  dd = delta/(1000L*60L*60L*24L);              delta = delta%(1000L*60L*60L*24L);
               long  hh = delta/(1000L*60L*60L);                  delta = delta%(1000L*60L*60L);
               long  mm = delta/(1000L*60L);                      delta = delta%(1000L*60L);
               long  ss = delta/(1000L);
            </PRE>
         </BLOCKQUOTE>
      ------------------------------------------------------------------------------------------ */
      delta = delta * 1000000L;
      /*.
      ==========================================================================================
      Get the years component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L*60L*60L*24L*30436875L*12L)).intValue()
            )
         );
      delta = delta % (1000L*60L*60L*24L*30436875L*12L);
      /*.
      ==========================================================================================
      Get the months component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L*60L*60L*24L*30436875L)).intValue()
            )
         );
      delta = delta % (1000L*60L*60L*24L*30436875L);
      delta = delta/1000000;  // here's the scale-down
      /*.
      ==========================================================================================
      Get the days component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L*60L*60L*24L)).intValue()
            )
         );
      delta = delta % (1000L*60L*60L*24L);
      /*.
      ==========================================================================================
      Get the hours component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L*60L*60L)).intValue()
            )
         );
      delta = delta % (1000L*60L*60L);
      /*.
      ==========================================================================================
      Get the minutes component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L*60L)).intValue()
            )
         );
      delta = delta % (1000L*60L);
      /*.
      ==========================================================================================
      Get the seconds component
      ------------------------------------------------------------------------------------------ */
      result.add
         (
         new Integer
            (
            new Long(delta/(1000L)).intValue()
            )
         );

      return result;
      }



   /*:                                    :METHOD:015:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method gets the class name of an object.

   <P><B>Implementation: </B><A HREF="Util.java.html#015">View source</A>

   @return
      The name of the object's class

   @param
      pObj is the reference object to get the class name for.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static XString className(Object pObj)
      {
      return new XString(pObj.getClass().getName());
      }



   /*:                                    :METHOD:016:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method checks to see if any of the Thread objects in an ArrayList of Thread objects are still
   running.

   <P><B>Implementation: </B><A HREF="Util.java.html#016">View source</A>

   @return
      True if any of the Threads in the array are alive, false otherwise.

   @param
      pThreads is an ArrayList of Thread objects.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean anyAlive(Thread[] pThreads)
      {
      for (int i=0; i<pThreads.length; i++)
         {
         if (pThreads[i].isAlive())
            {
            return true;
            }
         }
      return false;
      }



   /*:                                    :METHOD:017:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sifts an input array list of file names into one or more output array lists. It places
   all file names in the input array list that have the same root into different output array lists.<P>

   For example, if the input array list contains these file names:
      <BLOCKQUOTE>
         <PRE id="unindent">
            bi100-APPROVED.1
            bi100-APPROVED.2
            bi100-APPROVED.3
            bi100-APPROVED.xml
            bi105-APPROVED.1
            bi105-APPROVED.2
            bi105-APPROVED.3
            bi105-APPROVED.xml
            bi112-APPROVED.1
            bi112-APPROVED.2
            bi112-APPROVED.3
            bi112-APPROVED.xml
            bi114-APPROVED.1
            bi114-APPROVED.2
            bi114-APPROVED.3
            bi114-APPROVED.xml
            COL1080-APPROVED.1
            COL1080-APPROVED.2
            COL1080-APPROVED.3
            COL1080-APPROVED.xml
         </PRE>
      </BLOCKQUOTE>

   It will sift the names into these 4 array lists:
      <BLOCKQUOTE>
         <PRE id="unindent">
             ========== 00 ==========
             COL1080-APPROVED.1
             bi100-APPROVED.1
             bi105-APPROVED.1
             bi112-APPROVED.1
             bi114-APPROVED.1
             ------------------------

             ========== 01 ==========
             COL1080-APPROVED.2
             bi100-APPROVED.2
             bi105-APPROVED.2
             bi112-APPROVED.2
             bi114-APPROVED.2
             ------------------------

             ========== 02 ==========
             COL1080-APPROVED.3
             bi100-APPROVED.3
             bi105-APPROVED.3
             bi112-APPROVED.3
             bi114-APPROVED.3
             ------------------------

             ========== 03 ==========
             COL1080-APPROVED.xml
             bi100-APPROVED.xml
             bi105-APPROVED.xml
             bi112-APPROVED.xml
             bi114-APPROVED.xml
             ------------------------
         </PRE>
      </BLOCKQUOTE>

   <P><B>Implementation: </B><A HREF="Util.java.html#017">View source</A>

   @return
      An array list containing the output array lists

   @param
      pOriginalList is the input array list of file names that gets sifted.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ListOfLists<XString> siftFileNames(ArrayList<XString> pOriginalList)
      {
      /*.
      ==========================================================================================
      This is the array list of output array lists. It will have at least one output array list
      in it.
      ------------------------------------------------------------------------------------------ */
      ListOfLists<XString> results = new ListOfLists<XString>();
      results.add(new ArrayList<XString>());
      /*.
      ==========================================================================================
      Sort the input array list
      ------------------------------------------------------------------------------------------ */
      pOriginalList = Util.sortedArray(pOriginalList);
      /*.
      ==========================================================================================
      Iterate through the input array list, sifting consecutive file names that have identical
      root parts into separate array lists.
      ------------------------------------------------------------------------------------------ */
      int      arrayIdx = 0;
      XString  currRoot = new XString("");
      for (XString thisLine : pOriginalList)
         {
         /*.
         ==========================================================================================
         Get the next file name from the input array list and extract the root part of the name
         (the name without the extension).
         ------------------------------------------------------------------------------------------ */
         int      dotIdx   = thisLine.lastIndexOf('.');
         XString  thisRoot = (dotIdx == (-1))? (thisLine) : (thisLine.substring(0,dotIdx));
         /*.
         ==========================================================================================
         If the root is the same as the root of the previous file name, prepare to put this file
         name into the next consecutive output array list.
         ------------------------------------------------------------------------------------------ */
         if (thisRoot.equals(currRoot))
            {
            arrayIdx++;
            if (arrayIdx >= results.size())
               {
               results.add(new ArrayList<XString>());
               }
            }
         /*.
         ==========================================================================================
         Otherwise, this root is different from the previous one so prepare to put this file name
         into the first output array list
         ------------------------------------------------------------------------------------------ */
         else
            {
            currRoot = thisRoot;
            arrayIdx = 0;
            }
         /*.
         ==========================================================================================
         Put the file name into the selected output array list
         ------------------------------------------------------------------------------------------ */
         ArrayList<XString>  thisArray = results.get(arrayIdx);
         thisArray.add(thisLine);
         }
      /*.
      ==========================================================================================
      Return the array list of output array lists
      ------------------------------------------------------------------------------------------ */
      return results;
      }



   /*:                                    :METHOD:018:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Causes the currently executing thread to sleep (temporarily cease execution) for the specified
   number of milliseconds. The thread does not lose ownership of any monitors.<P>

   This is a cover function for the Thread.sleep() method. This one doesn't throw the useless exception
   that Thread.sleep() throws.

   <P><B>Implementation: </B><A HREF="Util.java.html#018">View source</A>

   @param
      pMillis is the length of time to sleep in milliseconds.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void sleep(long pMillis)
      {
      try
         {
         Thread.sleep(pMillis);
         }
      catch (Exception exception)
         {
         }
      }



   /*:                                    :METHOD:019:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns a code indicating what OS this program is running on.

   <P><B>Implementation: </B><A HREF="Util.java.html#019">View source</A>

   @return
      One of: Util.OS_WINDOWS9X, Util.OS_WINDOWS, or Util.OS_UNIX
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static int OS()
      {
      XString  os = new XString(System.getProperty("os.name").toLowerCase());
      /*.
      ==========================================================================================
      The commandline to run the program is dependent on the os.
      ------------------------------------------------------------------------------------------ */
      if (os.indexOf("windows 9") > -1)    // tired old DOS-based Windows
         {
         return Util.OS_WINDOWS9X;
         }
      else if (os.indexOf("windows") > -1) // Windows NT, 2000, XP and up
         {
         return Util.OS_WINDOWS;
         }
      else                                 // assume some variation of UNIX
         {
         return Util.OS_UNIX;
         }
      }
   public static final int  OS_WINDOWS9X = 0;
   public static final int  OS_WINDOWS   = 1;
   public static final int  OS_UNIX      = 2;



   /*:                                    :METHOD:020:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns true if this program is running on any version of the Windows OS.

   <P><B>Implementation: </B><A HREF="Util.java.html#020">View source</A>

   @return
      True if this program is running on any version of the Windows OS.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean isWindowsOS()
      {
      return (Util.OS() != Util.OS_UNIX);
      }



   /*:                                    :METHOD:021:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns true if this program is running on an operating system that is case sensitive in
   its file and directory naming rules.

   <P><B>Implementation: </B><A HREF="Util.java.html#021">View source</A>

   @return
      True if this program is running on an operating system that is case sensitive in its file and
      directory naming rules.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean fileNamesAreCaseSensitive()
      {
      switch (Util.OS())
         {
         default:
            return true;
         case Util.OS_WINDOWS9X:
         case Util.OS_WINDOWS:
            return false;
         }
      }



   /*:                                    :METHOD:022:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method passes a string containing an operating system shell command to the OS shell for
   execution in a separate process.<P>

   For example, if you want to run a Unix copy command to copy file1 to file2 from inside your Java
   code, you could call this method like this:
      <BLOCKQUOTE>
         <PRE id="unindent">
            int exitCode = runExternalProgram("cp file1 file2");
         </PRE>
      </BLOCKQUOTE>

   Here's another example that shows that pipes and redirection work as normal in the command string:
      <BLOCKQUOTE>
         <PRE id="unindent">
            runExternalProgram("java cosmicabyss.com.utl.Test | sort > x.x");
         </PRE>
      </BLOCKQUOTE>

   <P><B>Implementation: </B><A HREF="Util.java.html#022">View source</A>

   @return
      The exit code that the external program returns. By convention, the value 0 indicates normal
      termination.

   @param
      pCommand is the shell or OS command to run the external program.

   !! CONSIDER USING runDosCmd() INSTEAD OF THIS. THIS WORKS FINE ON SINGLE PROCESSOR MACHINES !!
   !! BUT SEEMS TO GET INTO RACES PRINTING OUTPUT ON MULTIPROCESSOR MACHINES !

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> int runExternalProgram(Type1 pCommand) throws Exception
      {
      XString  cmd   = XString.toXString(pCommand);
      Process  proc  = null;
      Runtime  rt    = Runtime.getRuntime();
      /*.
      ==========================================================================================
      The commandline to run the program is dependent on the os.
      ------------------------------------------------------------------------------------------ */
      switch (OS())
         {
         case Util.OS_WINDOWS9X:
            proc = rt.exec("command.com /c " + cmd);
            break;
         case Util.OS_WINDOWS:
            proc = rt.exec("cmd.exe /c " + cmd);
            break;
         case Util.OS_UNIX:
            proc = rt.exec(cmd.string());
            break;
         }
      /*.
      ==========================================================================================
      Send stderr messages to cOut
      ------------------------------------------------------------------------------------------ */
      StreamGobbler stderrGobbler = new StreamGobbler(proc.getErrorStream(), "  stderr");
      stderrGobbler.start();
      /*.
      ==========================================================================================
      Send stdout messages to cOut
      ------------------------------------------------------------------------------------------ */
      StreamGobbler stdoutGobbler = new StreamGobbler(proc.getInputStream(), "  stdout");
      stdoutGobbler.start();
      /*.
      ==========================================================================================
      Wait until all streams have been gobbled up
      ------------------------------------------------------------------------------------------ */
      StreamGobbler.waitForGobbling();
      /*.
      ==========================================================================================
      Wait for the process to exit and then return its exit code.
      ------------------------------------------------------------------------------------------ */
      return proc.waitFor();
      }



   /*:                                    :METHOD:023:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method clears the console screen

   <P><B>Implementation: </B><A HREF="Util.java.html#023">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void cls() throws Exception
      {
      new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
      }



   /*:                                    :METHOD:024:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method runs an arbitrary Dos command

   <P><B>Implementation: </B><A HREF="Util.java.html#024">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> void runDosCmd(Type1 pCmd) throws Exception
      {
      new ProcessBuilder("cmd", "/c", UString.toString(pCmd)).inheritIO().start().waitFor();
      }



   /*:                                    :METHOD:025:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method asks the user to enter a password on the command line and and masks the password with
   "*"s as it's being typed in

   <P><B>Implementation: </B><A HREF="Util.java.html#025">View source</A>

   @return
      The password that was entered

   @param
      pPrompt is the prompt displayed to the user
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString getPassword(Type1 pPrompt)
      {
      /*.
      ==========================================================================================
      Use a java swing dialog box to ask for the password and mask it as it's being entered.
      ------------------------------------------------------------------------------------------ */
      PasswordDialog  dialog  = new PasswordDialog(pPrompt);
      /*.
      ==========================================================================================
      Get the password that was entered in the dialog box and convert it to lower case to try to
      eliminate an erroneous password being entered because the shift key is accidently touched
      or the caps lock key is set
      ------------------------------------------------------------------------------------------ */
      XString  password = dialog.getText();
      if (password != null)
         {
         password = password.toLowerCase();
         }
      /*.
      ==========================================================================================
      Free up the swing object
      ------------------------------------------------------------------------------------------ */
      dialog = null;
      /*.
      ==========================================================================================
      And return the password that was entered.
      ------------------------------------------------------------------------------------------ */
      return password;
      }



   /*:                                    :METHOD:026:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a unique file name for a file in the default temporary-file directory. Calling
   this method is equivalent to calling getTempFileName(null,null).<P>

   The file is not actually created on the file system as it would be if java.io.File.createTempFile()
   were used to get a temporary file name.<P>

   Here is an example:
      <BLOCKQUOTE>
         <PRE id="unindent">
            In the following example, the default temporary directory is
            assumed to be "C:\Temp"

               C:\Temp\19216811026f8aa9fb10f0336aa0b7ffa.tmp
               |______||_______________________________||__|
                   |                   |                  |
                   |                   |                  +---- the specified suffix
                   |                   +----------------------- a GUID
                   +------------------------------------------- the name of the default temp directory
         </PRE>
      </BLOCKQUOTE>

   <P><B>Implementation: </B><A HREF="Util.java.html#026">View source</A>

   @return
      A unique file name for a file in the default temporary-file directory. The file is not actually
      created (as it would be if java.io.File.createTempFile() were used to get a temporary file name.)
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static XString getTempFileName() throws Exception
      {
      return getTempFileName(null,null);
      }



   /*:                                    :METHOD:027:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a unique file name for a file in the default temporary-file directory, using the
   given prefix and suffix to generate its name.<P>

   The file is not actually created on the file system as it would be if java.io.File.createTempFile()
   were used to get a temporary file name.<P>

   If the prefix does not end in a '.' character, then one is appended to the end of the prefix string
   before it is used in the construction of the file name.<P>

   If the suffix does not begin in a '.' character, then one is prepended to the front of the suffix
   string before it is used in the construction of the file name.<P>

   Here are some examples:<P>
      <BLOCKQUOTE>
         <PRE id="unindent">
            In all the following examples, the default temporary directory is
            assumed to be "C:\Temp"

            if both a prefix and a suffix are provided:
               C:\Temp\prefix.19216811026f8aa9fb10f0336aa0b7ffa.suffix
               |______||_____||_______________________________||_____|
                   |      |                   |                   |
                   |      |                   |                   +---- the specified suffix
                   |      |                   +------------------------ a GUID
                   |      +-------------------------------------------- the specified prefix
                   +--------------------------------------------------- the name of the default temp directory

            if a suffix is provided but the prefix is null or the empty string:
               C:\Temp\19216811026f8aa9fb10f0336aa0b7ffa.suffix
               |______||_______________________________||_____|
                   |                   |                   |
                   |                   |                   +---- the specified suffix
                   |                   +------------------------ a GUID
                   +-------------------------------------------- the name of the default temp directory

            if the prefix is provided but the suffix is null or the empty string:
               C:\Temp\prefix.19216811026f8aa9fb10f0336aa0b7ffa.tmp
               |______||_____||_______________________________||__|
                   |      |                   |                  |
                   |      |                   |                  +---- the default suffix
                   |      |                   +----------------------- a GUID
                   |      +------------------------------------------- the specified prefix
                   +-------------------------------------------------- the name of the default temp directory

            if both the prefix and the suffix are null or the empty string:
               C:\Temp\19216811026f8aa9fb10f0336aa0b7ffa.tmp
               |______||_______________________________||__|
                   |                   |                  |
                   |                   |                  +---- the specified suffix
                   |                   +----------------------- a GUID
                   +------------------------------------------- the name of the default temp directory

            Here are some actual results:
               getTempFileName(null,null) --------------------- C:\Temp\192168110271360b6910f0381268b8000.tmp
               getTempFileName(null,".suffix") ---------------- C:\Temp\192168110271360b6910f0381268b7fff.suffix
               getTempFileName("prefix",null) ----------------- C:\Temp\prefix.192168110271360b6910f0381268b7ffe.tmp
               getTempFileName("","") ------------------------- C:\Temp\192168110271360b6910f0381268b7ffd.tmp
               getTempFileName("",".suffix") ------------------ C:\Temp\192168110271360b6910f0381268b7ffc.suffix
               getTempFileName("prefix","") ------------------- C:\Temp\prefix.192168110271360b6910f0381268b7ffb.tmp
               getTempFileName("prefix",".suffix") ------------ C:\Temp\prefix.192168110271360b6910f0381268b7ffa.suffix
               getTempFileName("prefix.",".suffix") ----------- C:\Temp\prefix.192168110271360b6910f0381268b7ff9.suffix
               getTempFileName("prefix","suffix") ------------- C:\Temp\prefix.192168110271360b6910f0381268b7ff8.suffix
               getTempFileName(".",".") ----------------------- C:\Temp\192168110271360b6910f0381268b7ff7.tmp
               getTempFileName("..","..") --------------------- C:\Temp\192168110271360b6910f0381268b7ff6.tmp
               getTempFileName("prefix...","...suffix") ------- C:\Temp\prefix...192168110271360b6910f0381268b7ff5...suffix
               getTempFileName("...prefix...","...suffix...") - C:\Temp\prefix...192168110271360b6910f0381268b7ff4...suffix
         </PRE>
      </BLOCKQUOTE>

   <P><B>Implementation: </B><A HREF="Util.java.html#027">View source</A>

   @return
      A unique file name for a file in the default temporary-file directory. The file is not actually
      created (as it would be if java.io.File.createTempFile() were used to get a temporary file name.)

   @param
      pPrefix is the prefix string to be used in generating the file's name; may be null.
   @param
      pSuffix is the suffix string to be used in generating the file's name; may be null, in which case
      the suffix ".tmp" will be used
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1,Type2> XString getTempFileName(Type1 pPrefix, Type2 pSuffix) throws Exception
      {
      XString  prefix = new XString((pPrefix==null)? "" : pPrefix);
      XString  suffix = new XString((pSuffix==null)? "" : pSuffix);
      /*.
      ==========================================================================================
      Find out what the default temp directory is. This will be prepended to the file name so
      that if the file is created as named, it will be created in the default temp directory.
      ------------------------------------------------------------------------------------------ */
      XString  tempDirName = new XString(System.getProperty("java.io.tmpdir"));
      /*.
      ==========================================================================================
      Just to be safe, make sure there is a slash on the end of the default temp directory name.
      ------------------------------------------------------------------------------------------ */
      if ( !(tempDirName.endsWith("/") || tempDirName.endsWith("\\")) )
         {
         tempDirName = tempDirName.concat(System.getProperty("file.separator"));
         }
      /*.
      ==========================================================================================
      Apply some rules to the prefix
      ------------------------------------------------------------------------------------------ */
      if ((prefix==null) || prefix.equals(""))
         {
         prefix = new XString("");
         }
      else
         {
         if ( ! prefix.endsWith("."))
            {
            prefix = prefix.concat(".");
            }
         }
      while (prefix.startsWith("."))
         {
         prefix = prefix.trimLeft(".");
         }
      if (prefix.containsOnlyCharsInString("."))
         {
         prefix = new XString("");
         }
      /*.
      ==========================================================================================
      Apply some rules to the suffix
      ------------------------------------------------------------------------------------------ */
      if ((suffix==null) || suffix.equals(""))
         {
         suffix = new XString(".tmp");
         }
      else
         {
         if ( ! suffix.startsWith("."))
            {
            suffix = new XString("." + suffix.toString());
            }
         }
      while (suffix.endsWith("."))
         {
         suffix = suffix.trimRight(".");
         }
      if (suffix.equals("") || suffix.containsOnlyCharsInString("."))
         {
         suffix = new XString(".tmp");
         }
      /*.
      ==========================================================================================
      Now construct the name and return it.
      ------------------------------------------------------------------------------------------ */
      return new XString
         (
         tempDirName.string()    +
         prefix.string()         +
         (new GUID()).toString() +
         suffix.string()
         );
      }



   /*:                                    :METHOD:028:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method provides a generic mechanism for invoking a PUBLIC method that is passed by name as an
   xString argument. It invokes the method identified by pMethodName on the object pObject with the
   arguments pArguments and returns an object of Type1. In other words, it is equivalent to invoking
   the method that has this signature:
      <BLOCKQUOTE>
         <PRE id="unindent">
            public Type1 pObject.pMethodName(pArguments)
         </PRE>
      </BLOCKQUOTE>

   If the method completes normally, the value it returns is returned to the caller of invoke; if the
   value has a primitive type, it is first appropriately wrapped in an object. However, if the value
   has the type of an array of a primitive type, the elements of the array are not wrapped in objects;
   in other words, an array of primitive type is returned. If the underlying method return type is
   void, the invocation returns null.

   <P><B>Implementation: </B><A HREF="Util.java.html#028">View source</A>

   @return
      The result of calling the method represented by pMethodName on pObject with parameters
      pArguments.

   @param
      pObject is the object the underlying method (pMethodName) is invoked from.
   @param
      pMethodName the name of the pObject method to invoke.
   @param
      pArguments are the arguments used for the method call.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   @SuppressWarnings("unchecked")
   public static <Type1,Type2> Type1 invoke(Type2 pObject, XString pMethodName, Object... pArguments) throws Exception
      {
      /*.
      ==========================================================================================
      If there are arguments to pass to the method, iterate through the array of arguments and
      get the Class of each one. If there are no arguments, we will just be passing a null into
      the getMethod() call below.
      ------------------------------------------------------------------------------------------ */
      Class<?>[]  argumentsClasses = null;
      if (pArguments != null)
         {
         argumentsClasses = new Class[pArguments.length];
         for (int i=0; i<pArguments.length; i++)
            {
            argumentsClasses[i] = pArguments[i].getClass();
            }
         }
      /*.
      ==========================================================================================
      Find the method that matches the signature implied by pObject, pMethodName, and
      pArguments.
      ------------------------------------------------------------------------------------------ */
      Class<?>  theClass  = pObject.getClass();
      Method    theMethod = theClass.getMethod(pMethodName.string(),argumentsClasses);
      /*.
      ==========================================================================================
      Invoke public Type1 pObject.theMethod(pArguments)
         Note: casting the return value to Type1 here is why the unchecked cast warning is
               Issued by the compiler and is the reason for the suppressWarnings directive for
               this method. I can't figure any better way around the warning right now.
      ------------------------------------------------------------------------------------------ */
      return (Type1)theMethod.invoke(pObject,pArguments);
      }



   /*:                                    :METHOD:029:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method provides a generic mechanism for invoking a PUBLIC STATIC method that is passed by name
   as an XString argument. It invokes the method identified by pMethodName on the class identified by
   pClass with the arguments pArguments and returns an object of Type1. In other words, it is
   equivalent to invoking the method that has this signature:
      <BLOCKQUOTE>
         <PRE id="unindent">
            public static Type1 pClass.pMethodName(pArguments)
         </PRE>
      </BLOCKQUOTE>

   If the method completes normally, the value it returns is returned to the caller of invoke; if the
   value has a primitive type, it is first appropriately wrapped in an object. However, if the value
   has the type of an array of a primitive type, the elements of the array are not wrapped in objects;
   in other words, an array of primitive type is returned. If the underlying method return type is
   void, the invocation returns null.

   <P><B>Implementation: </B><A HREF="Util.java.html#029">View source</A>

   @return
      The result of calling the method represented by pMethodName on pClass with parameters pArguments.

   @param
      pClass is the class the underlying method (pMethodName) is invoked from.
   @param
      pMethodName the name of the pClass method to invoke.
   @param
      pArguments are the arguments used for the method call.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   @SuppressWarnings("unchecked")
   public static <Type1> Type1 invoke(Class pClass, XString pMethodName, Object... pArguments) throws Exception
      {
      /*.
      ==========================================================================================
      If there are arguments to pass to the method, iterate through the array of arguments and
      get the Class of each one. If there are no arguments, we will just be passing a null into
      the getMethod() call below.
      ------------------------------------------------------------------------------------------ */
      Class<?>[]  argumentsClasses = null;
      if (pArguments != null)
         {
         argumentsClasses = new Class[pArguments.length];
         for (int i=0; i<pArguments.length; i++)
            {
            argumentsClasses[i] = pArguments[i].getClass();
            }
         }
      /*.
      ==========================================================================================
      Find the method that matches the signature implied by pClass, pMethodName, and pArguments.
      ------------------------------------------------------------------------------------------ */
      Method  theMethod = pClass.getMethod(pMethodName.string(),argumentsClasses);
      /*.
      ==========================================================================================
      Invoke public static Type1 pClass.theMethod(pArguments)
         Note: casting the return value to Type1 here is why the unchecked cast warning is
               Issued by the compiler and is the reason for the suppressWarnings directive for
               this method. I can't figure any better way around the warning right now.
      ------------------------------------------------------------------------------------------ */
      return (Type1)theMethod.invoke(pClass,pArguments);
      }



   /*:                                    :METHOD:030:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method provides a generic mechanism for invoking a PUBLIC STATIC method that is passed as a
   Method argument. It invokes the method identified by pMethod with the arguments pArguments and
   returns an object of Type1. In other words, it is equivalent to invoking the method that has this
   signature:
      <BLOCKQUOTE>
         <PRE id="unindent">
            public static Type1 pMethod(pArguments)
         </PRE>
      </BLOCKQUOTE>

   If the method completes normally, the value it returns is returned to the caller of invoke; if the
   value has a primitive type, it is first appropriately wrapped in an object. However, if the value
   has the type of an array of a primitive type, the elements of the array are not wrapped in objects;
   in other words, an array of primitive type is returned. If the underlying method return type is
   void, the invocation returns null.

   <P><B>Implementation: </B><A HREF="Util.java.html#030">View source</A>

   @return
      The result of calling the method represented by pMethod with parameters pArguments.

   @param
      pMethod is the method to invoke.
   @param
      pArguments are the arguments used for the method call.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   @SuppressWarnings("unchecked")
   public static <Type1> Type1 invoke(Method pMethod, Object... pArguments) throws Exception
      {
      /*.
      ==========================================================================================
      If there are arguments to pass to the method, iterate through the array of arguments and
      get the Class of each one. If there are no arguments, we will just be passing a null into
      the getMethod() call below.
      ------------------------------------------------------------------------------------------ */
      Class<?>[]  argumentsClasses = null;
      if (pArguments != null)
         {
         argumentsClasses = new Class[pArguments.length];
         for (int i=0; i<pArguments.length; i++)
            {
            argumentsClasses[i] = pArguments[i].getClass();
            }
         }
      /*.
      ==========================================================================================
      Invoke public static Type1 pClass.theMethod(pArguments)
         Note: the return value to Type1 here is why the unchecked cast warning is issued by the
               Compiler and is the reason for the suppressWarnings directive for this method. I
               can't figure any better way around the warning right now.
      ------------------------------------------------------------------------------------------ */
      return (Type1)pMethod.invoke(null, pArguments);
      }



   /*:                                    :METHOD:031:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns true if the given year is a leap year

   <P><B>Implementation: </B><A HREF="Util.java.html#031">View source</A>

   @return
      True is the year passed in through pYYYY is a leap year, false otherwise.

   @param
      PYYYY is the year to apply the leap year test to.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean isLeapYear(int pYYYY)
      {
      if      ((pYYYY % 400) == 0) return  true;
      else if ((pYYYY % 100) == 0) return  false;
      else if ((pYYYY % 4  ) == 0) return  true;
      else                         return  false;
      }



   /*:                                    :METHOD:032:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns true if the given year/month/day combination is valid; IOW, did that or will the
   specified day exist.

   <P><B>Implementation: </B><A HREF="Util.java.html#032">View source</A>

   @return
      This method returns true if the given year/month/day combination is valid.

   @param
      PYYYY is the year, e.g., 1955, 1997, 2001, 2036
   @param
      PMM is the month, e.g., 1 for January, 2 for February, ...
   @param
      Pdd is the day of the month, e.g., 1, 2, 3, ... 30, 31
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean isValidDayOfMonth(int pYYYY, int pMM, int pdd)
      {
      boolean  isValid = false;
      /*.
      ==========================================================================================
      Rules for valid days of month for January thru July
         <BLOCKQUOTE>
            <PRE id="unindent">
               1) opdd numbered months have 31 days
               2) february has 29 days in leap years and 28 days otherwise.
               3) all other even numbered months have 30 days
            </PRE>
         </BLOCKQUOTE>
      ------------------------------------------------------------------------------------------ */
      if (pMM <= 7)
         {
         if (UMath.isOdd(pMM))
            {
            isValid = UMath.isInRange(pdd , 1, 31);
            }
         else if (pMM == 2)
            {
            if (Util.isLeapYear(pYYYY))
               {
               isValid = UMath.isInRange(pdd , 1, 29);
               }
            else
               {
               isValid = UMath.isInRange(pdd , 1, 28);
               }
            }
         else
            {
            isValid = UMath.isInRange(pdd , 1, 30);
            }
         }
      /*.
      ==========================================================================================
      Rules for valid days of month for August thru December
         1) even numbered months have 31 days 2) opdd numbered months have 30 days
      ------------------------------------------------------------------------------------------ */
      else
         {
         if (UMath.isEven(pMM))
            {
            isValid = UMath.isInRange(pdd , 1, 31);
            }
         else
            {
            isValid = UMath.isInRange(pdd , 1, 30);
            }
         }
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return isValid;
      }



   /*:                                    :METHOD:033:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method determines if the specified character is a letter

   <P><B>Implementation: </B><A HREF="Util.java.html#033">View source</A>

   @return
      True if pC is a letter, false otherwise.

   @param
      PC is the character to test.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static boolean isLetter(char pC)
      {
      return ( (('A' <= pC) && (pC <= 'Z')) || (('a' <= pC) && (pC <= 'z')) );
      }



   /*:                                    :METHOD:034:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method replaces all the non-letter characters in the string with blanks.

   <P><B>Implementation: </B><A HREF="Util.java.html#034">View source</A>

   @return
      A new XString with all the non-letter characters in the original string replaced with blanks.

   @param
      pStr is the string to replace all the non-letters with blanks in.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString lettersOnly(Type1 pStr)
      {
      char[]  chars = (new XString(pStr)).toCharArray();
      for (int i=0; i<chars.length; i++)
         {
         char c = chars[i];
         if (! isLetter(c))
            {
            chars[i] = ' ';
            }
         }
      return new XString(chars);
      }



   /*:                                    :METHOD:035:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method replaces all the one-letter words with blanks.

   <P><B>Implementation: </B><A HREF="Util.java.html#035">View source</A>

   @return
      A new XString with all the one-letter words in the original string replaced with blanks.

   @param
      pStr is the string to replace all the one-letter words with blanks in.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString deleteOneLetterWords(Type1 pStr)
      {
      boolean prevIsBlank = true;
      boolean nextIsBlank = false;
      char[]  chars = (new XString(pStr)).toCharArray();
      for (int i=0; i<chars.length; i++)
         {
         nextIsBlank =  (i >= (chars.length-1))? true : !isLetter(chars[i+1]);
         if (prevIsBlank && nextIsBlank)
            {
            chars[i] = ' ';
            }
         prevIsBlank = !isLetter(chars[i]);
         }
      return new XString(chars);
      }



   /*:                                    :METHOD:036:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the available provider implementations for a given service type if the service
   type name begins with the filter string.

   For example, to get the names of all of a provider's cipher implementations that begin with the
   substring "PBE", make the follow call:
      ArrayList<String> ciphers = getJceProviderFilteredImplementations("Cipher", "PBE");

   This will return a list such as:
      <BLOCKQUOTE>
         <PRE id="unindent">
            PBEwithMD2andDES
            PBEwithMD5and128bitAES-CBC-OPENSSL
            PBEwithMD5and192bitAES-CBC-OPENSSL
            :
         </PRE>
      </BLOCKQUOTE>

   <P><B>Implementation: </B><A HREF="Util.java.html#036">View source</A>

   @return
      An Arraylist of Strings. Each string is the name of one implementation.

   @param
      pProviderName is the name of the installed provider whose implementations are returned. If
      pProviderName is not included in the parameter list, then the default provider's (BouncyCastle)
      name "BC" is used.
   @param
      pServiceType is the name of the service whose implementations are returned. Here's a [partial]
      list of service types:
         <BLOCKQUOTE>
            <PRE id="unindent">
               AlgorithmParameterGenerator
               AlgorithmParameters
               CertPathBuilder
               CertPathValidator
               CertStore
               CertificateFactory
               Cipher
               GssApiMechanism
               KeyAgreement
               KeyFactory
               KeyGenerator
               KeyManagerFactory
               KeyPairGenerator
               KeyStore
               Mac
               MessageDigest
               SSLContext
               SecretKeyFactory
               SecureRandom
               Signature
               TrustManagerFactory
            </PRE>
         </BLOCKQUOTE>
   @param
      pFilter is a substring that is used to eliminate results. Any implementation name that does not
      start with pFilter is not returned in the ArrayList. All implementation names of the specified
      ServiceType that are implemented by the specified Provider that begin with the substring
      specified by pFilter are returned in the ArrayList. If pFilter is not included in the parameter
      list, then the default filter "PBE" is used.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ArrayList<String> getJceProviderFilteredImplementations(String pProviderName, String pServiceType, String pFilter)
      {
      ArrayList<String>  result = new ArrayList<String>();
      /*.
      ==========================================================================================
      Query to get a list of all the installed Java JCE framework Providers (like BouncyCastle)
      ------------------------------------------------------------------------------------------ */
      Provider[]  providers = Security.getProviders();
      for (int i=0; i<providers.length; i++)
         {
         /*.
         ==========================================================================================
         If a specific provider has been requested (by not using the wildcard "*"), then skip any
         other providers that are not the requested one.
         ------------------------------------------------------------------------------------------ */
         if (!pProviderName.equals("*"))
            {
            if (!providers[i].getName().equals(pProviderName)) continue;
            }
         /*.
         ==========================================================================================
         For each Provider, search its keys for items of the requested service type.
         ------------------------------------------------------------------------------------------ */
         Set                keys         = providers[i].keySet();
         ArrayList<String>  serviceTypes = new ArrayList<String>();
         for (Iterator iter = keys.iterator(); iter.hasNext(); )
            {
            String key = (String)iter.next();
            key = key.split(" ")[0];
            /*.
            ==========================================================================================
            For each item of the requested service type, place that item into a sortable array and
            make the list more readable by useing lower case on the less important words.
            ------------------------------------------------------------------------------------------ */
            if (key.startsWith(pServiceType + "." + pFilter))
               {
               XString  cipher  =
                  (
                  (new XString(key.substring(pServiceType.length()+1))).
                  replaceAll("WITH","with").
                  replaceAll("With","with").
                  replaceAll("AND","and").
                  replaceAll("And","and").
                  replaceAll("KEY","Key").
                  replaceAll("TRIPLE","Triple").
                  replaceAll("BIT","bit")
                  );
               serviceTypes.add(cipher.toString());
               }
            }
         /*.
         ==========================================================================================
         Sort the array of requested service types and then place the sorted list into the results
         array
         ------------------------------------------------------------------------------------------ */
         serviceTypes = Util.sortedArrayList(serviceTypes);
         result.addAll(serviceTypes);
         }
      return result;
      }
   public static ArrayList<String> getJceProviderFilteredImplementations(String pServiceType, String pFilter)
      {
      return getJceProviderFilteredImplementations("*", pServiceType, "");
      }
   public static ArrayList<String> getJceProviderFilteredImplementations(String pServiceType)
      {
      return getJceProviderFilteredImplementations("*", pServiceType, "PBE");
      }



   /*:                                    :METHOD:037:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the available provider implementations for a given service type.

   <P><B>Implementation: </B><A HREF="Util.java.html#037">View source</A>

   @return
      An Arraylist of Strings. Each string is the name of one implementation.

   @param
      pProviderName is the name of the installed provider whose implementations are returned. If
      pProviderName is not included in the parameter list, then the default provider's (BouncyCastle)
      name "BC" is used.
   @param
      pServiceType is the name of the service whose implementations are returned. Here's a [partial]
      list of service types:
         <BLOCKQUOTE>
            <PRE id="unindent">
               AlgorithmParameterGenerator
               AlgorithmParameters
               CertPathBuilder
               CertPathValidator
               CertStore
               CertificateFactory
               Cipher
               GssApiMechanism
               KeyAgreement
               KeyFactory
               KeyGenerator
               KeyManagerFactory
               KeyPairGenerator
               KeyStore
               Mac
               MessageDigest
               SSLContext
               SecretKeyFactory
               SecureRandom
               Signature
               TrustManagerFactory
            </PRE>
         </BLOCKQUOTE>
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ArrayList<String> getJceProviderImplementations(String pProvider, String pServiceType)
      {
      return getJceProviderFilteredImplementations(pProvider, pServiceType, "");
      }
   public static ArrayList<String> getJceProviderImplementations(String pServiceType)
      {
      return getJceProviderFilteredImplementations("*", pServiceType, "");
      }



   /*:                                    :METHOD:038:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the key size for a given cipher identified by its name.

   <P><B>Implementation: </B><A HREF="Util.java.html#038">View source</A>

   @return
      An integer containing the Key Size for the specified cipher. If the Cipher is unknown to this
      method, then a result of 0 is returned.

   @param
      pCipherName is the name of the Cipher for which a key size is returned.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static int getJceCipherKeySize(String pCipherName)
      {
      String  cipherName = pCipherName.toUpperCase();

      if (cipherName.contains("_40"))                            return 40;
      if (cipherName.contains("_128"))                           return 128;
      if (cipherName.contains("_256"))                           return 256;
      if (cipherName.contains("1024BIT"))                        return 1024;
      if (cipherName.contains("512BIT"))                         return 512;
      if (cipherName.contains("384BIT"))                         return 384;
      if (cipherName.contains("256BIT"))                         return 256;
      if (cipherName.contains("224BIT"))                         return 224;
      if (cipherName.contains("192BIT"))                         return 192;
      if (cipherName.contains("160BIT"))                         return 160;
      if (cipherName.contains("128BIT"))                         return 128;
      if (cipherName.contains("64BIT"))                          return 64;
      if (cipherName.contains("40BIT"))                          return 40;
      if (cipherName.equals("PBEWITHMD2ANDDES"))                 return 64;
      if (cipherName.equals("PBEWITHMD2ANDRC2"))                 return 128;
      if (cipherName.equals("PBEWITHMD5ANDDES"))                 return 64;
      if (cipherName.equals("PBEWITHMD5ANDRC2"))                 return 128;
      if (cipherName.equals("PBEWITHSHA1ANDDES"))                return 64;
      if (cipherName.equals("PBEWITHSHA1ANDRC2"))                return 128;
      if (cipherName.equals("PBEWITHSHAAND2-KEYTRIPLEDES-CBC"))  return 128;
      if (cipherName.equals("PBEWITHSHAAND3-KEYTRIPLEDES-CBC"))  return 192;
      if (cipherName.equals("PBEWITHSHAAND128BITRC2-CBC"))       return 128;
      if (cipherName.equals("PBEWITHSHAAND40BITRC2-CBC"))        return 40;
      if (cipherName.equals("PBEWITHSHAAND128BITRC4"))           return 128;
      if (cipherName.equals("PBEWITHSHAAND40BITRC4"))            return 40;
      if (cipherName.equals("PBEWITHSHAANDTWOFISH-CBC"))         return 256;
      if (cipherName.equals("PBEWITHSHAANDIDEA-CBC"))            return 128;
      return 0;
      }



   /*:                                    :METHOD:039:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns the size for a given digest identified by its name.

   <P><B>Implementation: </B><A HREF="Util.java.html#039">View source</A>

   @return
      An integer containing the Output Size for the specified digest. If the digest is unknown to this
      method, then a result of 0 is returned.

   @param
      pDigestName is the name of the digest for which a size is returned.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static int getJceDigestOutputSize(String pDigestName)
      {
      String  digestName = pDigestName.toUpperCase();
      if (digestName.equals("GOST3411"))         return 256;
      if (digestName.equals("MD2"))              return 128;
      if (digestName.equals("MD4"))              return 128;
      if (digestName.equals("MD5"))              return 128;
      if (digestName.equals("RIPEMD128"))        return 128;
      if (digestName.equals("RIPEMD160"))        return 160;
      if (digestName.equals("RIPEMD256"))        return 256;
      if (digestName.equals("RIPEMD320"))        return 320;
      if (digestName.equals("SHA"))              return 160;   //    SHA-1
      if (digestName.equals("SHA1"))             return 160;   //    SHA-1
      if (digestName.equals("SHA-1"))            return 160;   //    SHA-1
      if (digestName.equals("SHA-224"))          return 224;   // SHA-2
      if (digestName.equals("SHA-256"))          return 256;   // SHA-2
      if (digestName.equals("SHA-384"))          return 384;   // SHA-2
      if (digestName.equals("SHA-512"))          return 512;   // SHA-2
      if (digestName.equals("SHA-512/224"))      return 224;   // SHA-2
      if (digestName.equals("SHA-512/256"))      return 256;   // SHA-2
      if (digestName.equals("SHA3-224"))         return 224;   //    SHA-3  ( Keccak )
      if (digestName.equals("SHA3-256"))         return 256;   //    SHA-3  ( Keccak )
      if (digestName.equals("SHA3-384"))         return 384;   //    SHA-3  ( Keccak )
      if (digestName.equals("SHA3-512"))         return 512;   //    SHA-3  ( Keccak )
      if (digestName.equals("SKEIN-256-128"))    return 128;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-256-160"))    return 160;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-256-224"))    return 224;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-256-256"))    return 256;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-128"))    return 128;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-160"))    return 160;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-224"))    return 224;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-256"))    return 256;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-384"))    return 384;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-512-512"))    return 512;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-1024-384"))   return 384;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-1024-512"))   return 512;   // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SKEIN-1024-1024"))  return 1024;  // based on Threefish. one of last 5 finalists to be SHA-3
      if (digestName.equals("SM3"))              return 256;
      if (digestName.equals("TIGER"))            return 192;
      if (digestName.equals("WHIRLPOOL"))        return 512;
      return 0;
      }



   /*:                                    :METHOD:040:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method takes an array of objects, converts each one to an XString, catenates all the resulting
   XStrings together -- each one separated from the previous by a space -- into one XString.

   <P><B>Implementation: </B><A HREF="Util.java.html#040">View source</A>

   @return
      An XString containing all the XString representations of the objects in an array concatenated
      together and separated by spaces.

   @param
      ppStrings is the array of objects that are converted to XStrigs and catenated together.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static <Type1> XString arrayToXString(Type1[] pStrings)
      {
      XString  result = XString.EMPTY;
      if (pStrings.length > 0)
         {
         result = new XString(pStrings[0]);
         for (int i = 1; i < pStrings.length; i++)
            {
            result = result.concat(" " + pStrings[i]);
            }
         }
      return result;
      }



   /*:                                    :METHOD:041:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This boilerplate method is used for testing an instantiated object of this class and may include any
   code the developer chooses.

   <P><B>Implementation: </B><A HREF="Util.java.html#041">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void test() throws Exception
      {
      cOut.titledPrintf
         (
         "\"HELLO WORLD!\"",
         "%s  %s  %s",
         "I'm an object of the", CLASS_NAME, "class, and I approved this message."
         );
      }



   /*:                                    :METHOD:042:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows this class file to be unit tested as a standalone application. It's the method
   that's called when the class is invoked from the command line by using the java application launcher
   - "java". Main() is not a required method, but the practice of putting one in each class and
   wrapping class test code within it allows easy unit testing of the class; and main does not need to
   be removed when testing is complete.

   <P>
      <DL>
         <DT>
            <B>
               Command line usage:
            </B>
            <DD>
               Java cosmicabyss.com.lib.Util
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="Util.java.html#042">View source</A>

   @param
      pArgs contains the command line arguments with which this class was invoked as an application.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void main(String[] pArgs) throws Exception
      {
      /*.
      ==========================================================================================
      Greetings !
      ------------------------------------------------------------------------------------------ */
      cOut.banner(CLASS_NAME);
      /*.
      ==========================================================================================
      Create an object and send its output to the ConsoleStream
      ------------------------------------------------------------------------------------------ */
      Util  obj = new Util();
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      obj.test();
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      long            nowTime          = System.currentTimeMillis();
      long            sixMonthsAgoTime = nowTime - (long)((long)183 * (long)24 * (long)60 * (long)60 * (long)1000);
      java.util.Date  sixMonthsAgoDate = new java.util.Date(sixMonthsAgoTime);
      XString         firstDate        = Util.timeStamp("yyyy.MM.dd",sixMonthsAgoDate);
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      ArrayList<XString> al = new ArrayList<XString>();
      al.add(new XString("bolivar.first"));
      al.add(new XString("bi105-APPROVED.2"));
      al.add(new XString("bi105-APPROVED.3"));
      al.add(new XString("bi105-APPROVED.xml"));
      al.add(new XString("bi112-APPROVED.1"));
      al.add(new XString("bi114-APPROVED.1"));
      al.add(new XString("COL1080-APPROVED.1"));
      al.add(new XString("COL1080-APPROVED.2"));
      al.add(new XString("bi100-APPROVED.1"));
      al.add(new XString("bi100-APPROVED.2"));
      al.add(new XString("bi100-APPROVED.3"));
      al.add(new XString("bi100-APPROVED.xml"));
      al.add(new XString("bi114-APPROVED.2"));
      al.add(new XString("bi112-APPROVED.2"));
      al.add(new XString("bi112-APPROVED.3"));
      al.add(new XString("bi112-APPROVED.xml"));
      al.add(new XString("bi114-APPROVED.3"));
      al.add(new XString("bi114-APPROVED.xml"));
      al.add(new XString("bi105-APPROVED.1"));
      al.add(new XString("COL1080-APPROVED.3"));
      al.add(new XString("COL1080-APPROVED.xml"));
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      al = shuffledArrayList(al);
      cOut.println("----------------------------");
      for (XString xstr : al)
         {
         cOut.println(xstr);
         }
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      ListOfLists<XString> aal = siftFileNames(al);
      for (ArrayList<XString> alx : aal)
         {
         cOut.println("----------------------------");
         for (XString xstr : alx)
            {
            cOut.println(xstr);
            }
         }

      cOut.println("password is: " + getPassword("enter the password"));
      }



   }  // class Util



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Notes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */