/*::.
==================================================================================================================================
=================================================¦ Copyright © 2007 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       XRandom.java
Originator: Allen Baker (2007.05.26 22:47)
LayoutRev:  5
================================================================================================================================== */



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



/*.
==========================================================================================
Imports
------------------------------------------------------------------------------------------ */
import java.io.*;
import java.util.*;



/*::
======================================================================================================================== *//**
This class provides methods to supplement the capabilities provided by a class that is part of the JDK, J2EE, or some
other 3rd party library. The extensions are provided by way of this subclass of the 3rd party class.<P>

In particular, this class extends the capabilities of the Random class by adding a couple of methods that generate
random XStrings of parameter-specified lengths.<P>

The following is the class description of the Random class, which this XRandom class inherits:
   <BLOCKQUOTE>
      An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed,
      which is modified using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume
      2, Section 3.2.1.) If two instances of Random are created with the same seed, and the same sequence of method
      calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this
      property, particular algorithms are specified for the class Random. Java implementations must use all the
      algorithms shown here for the class Random, for the sake of absolute portability of Java code. However, subclasses
      of class Random are permitted to use other algorithms, so long as they adhere to the general contracts for all the
      methods.

      The algorithms implemented by class Random use a protected utility method that on each invocation can supply up to
      32 pseudorandomly generated bits.<P>

      Many applications will find the method Math.random() simpler to use.<P>

      Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance
      across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom
      in multithreaded designs.<P>

      Instances of java.util.Random are not cryptographically secure. Consider instead using SecureRandom to get a
      cryptographically secure pseudo-random number generator for use by security-sensitive applications.
   </BLOCKQUOTE>

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  //.
                  ========================================================================================
                  Create an object
                  ---------------------------------------------------------------------------------------- //
                  XRandom  obj;
                  //.
                  ========================================================================================
                  Create a new XRandom instance initialized with a seed value of 2. Then generate a 60
                  character length random XString of printable characters in the ASCII character value range
                  of from space to tilde [32..126] and print it out.
                  ---------------------------------------------------------------------------------------- //
                  obj = new XRandom(2);
                  cOut.println(obj.nextAscii(60));
                  cOut.println();
                  //.
                  ========================================================================================
                  Create a new XRandom instance initialized with a seed value of 1. Then generate a 60
                  character length random XString of printable characters in the ASCII character value range
                  of from space to tilde [32..126] and print it out. It should be a different sequence of
                  characters from the one generated and printed just prior.
                  ---------------------------------------------------------------------------------------- //
                  obj = new XRandom(1);
                  cOut.println(obj.nextAscii(60));
                  cOut.println();
                  //.
                  ========================================================================================
                  Create a new XRandom instance initialized with a seed value of 2 again. Then generate a 60
                  character length random XString of printable characters in the ASCII character value range
                  of from space to tilde [32..126] and print it out. It should be the same sequence of
                  characters from the one generated and printed first.
                  ---------------------------------------------------------------------------------------- //
                  obj = new XRandom(2);
                  cOut.println(obj.nextAscii(60));
                  cOut.println();
                  //.
                  ========================================================================================
                  Create a new XRandom instance initialized without a specified seed value. Then generate a
                  60 character length random XString of printable characters in the ASCII character value
                  range of from space to tilde [32..126] and print it out. Then generate another from the
                  same seeded XRandom instance print it out too. The two sequences of characters should be
                  different from one another as well as different from all the ones printed earlier.
                  ---------------------------------------------------------------------------------------- //
                  obj = new XRandom();
                  cOut.println(obj.nextAscii(60));
                  cOut.println(obj.nextAscii(60));
                  cOut.println();
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="XRandom.java.html">
               xRandom.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class XRandom extends Random
   {



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a new random number generator instance. This constructor sets the seed of the
   random number generator to a value very likely to be distinct from any other invocation of this
   constructor.

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

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XRandom()
      {
      super();
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a new random number generator instance. It sets the seed of the random number
   generator using a single long seed. The general contract of setSeed is that it alters the state of
   this random number generator object so as to be in exactly the same state as if it had just been
   created with the argument seed as a seed. The method setSeed() is implemented by class Random by
   atomically updating the seed to (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1) and clearing the
   haveNextNextGaussian flag used by nextGaussian(). The implementation of setSeed by class Random
   happens to use only 48 bits of the given seed. In general, however, an overriding method may use all
   64 bits of the long argument as a seed value.

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

   @param
      pSeed is the initial seed for the XRandom instances that is created by this constructor.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XRandom(long pSeed)
      {
      super(pSeed);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method returns a random XString that is pLenth characters long containing a sequence of
   characters with each character in the full ASCII character range of [char(0)..char(127)].<P>

   It generates random bytes and places them into a byte array and then converts the bytes in the byte
   array to characters which are used to populate the XString that is returned. The number of random
   bytes produced is equal to the length of the random XString that was requested in the call to this
   method via the pLength parameter. Each byte is select as if by the following algorithm:
      <BLOCKQUOTE>
         <PRE id="unindent">
            *   public void nextBytes(byte[] bytes)
            *      {
            *      for (int i = 0; i < bytes.length; )
            *         {
            *         for(int rnd = nextInt(),  n = Math.min(bytes.length - i, 4);    n-- > 0;    rnd >>= 8)
            *            {
            *            bytes[i++] = (byte)rnd;
            *            }
            *         }
            *      }
         </PRE>
      </BLOCKQUOTE>

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

   @return
      A XString that is pLength characters long and made up of randomly selected characters.

   @param
      pLength is the length of the XString that will be returned.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XString nextXString(int pLength)
      {
      byte[]  bytes = new byte[pLength];
      nextBytes(bytes);
      return new XString(new String(bytes));
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method generates a random XString that is pLength characters long containing a sequence of
   characters with each character in the printable ASCII character range of space to tilde
   [(char)32..(char)126]. It effectively calls nextXString() to get a sequence of characters with each
   character in the full ASCII character range of [(char)0..(char)127] and then proceeds to hash each
   character into the printable ASCII character range<P>

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

   @return
      A XString that is pLength characters long made up of randomly selected characters in the range of
      the 95 characters from ' ' to '~'.

   @param
      pLength is the length of the XString that will be returned.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XString nextAscii(int pLength) throws Exception
      {
      return nextXString(pLength).asciiHash();
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the ConsoleStream for this object.

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

   @return
      A reference to this object

   @param
      pConsole is a ConsoleStream through which this objects sends its output.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XRandom setOut(ConsoleStream pConsole)
      {
      cOut = pConsole;
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   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="XRandom.java.html#005">View source</A>

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



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  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(XRandom.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();
   /*.
   ==========================================================================================
   Class variables
      cOut : console output.
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cOut = ConsoleStream.getSingleton();
   /*.
   ==========================================================================================
   Instance variables
      iVarName : something or other
   ------------------------------------------------------------------------------------------ */



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



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



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   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.XRandom
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="XRandom.java.html#006">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
      {
      /*.
      ==========================================================================================
      Create an object
      ------------------------------------------------------------------------------------------ */
      XRandom  obj = new XRandom();
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      obj.test();
      cOut.println();
      /*.
      ==========================================================================================
      Create a new XRandom instance initialized with a seed value of 2. Then generate a 60
      character length random XString of printable characters in the ASCII character value range
      of from space to tilde [(char)32..(char)126] and print it out.
      ------------------------------------------------------------------------------------------ */
      obj = new XRandom(2);
      cOut.println(obj.nextAscii(60));
      cOut.println();
      /*.
      ==========================================================================================
      Create a new XRandom instance initialized with a seed value of 1. Then generate a 60
      character length random XString of printable characters in the ASCII character value range
      of from space to tilde [(char)32..(char)126] and print it out. It should be a different
      sequence of characters from the one generated and printed just prior.
      ------------------------------------------------------------------------------------------ */
      obj = new XRandom(1);
      cOut.println(obj.nextAscii(60));
      cOut.println();
      /*.
      ==========================================================================================
      Create a new XRandom instance initialized with a seed value of 2 again. Then generate a 60
      character length random XString of printable characters in the ASCII character value range
      of from space to tilde [(char)32..(char)126] and print it out. It should be the same
      sequence of characters from the one generated and printed first.
      ------------------------------------------------------------------------------------------ */
      obj = new XRandom(2);
      cOut.println(obj.nextAscii(60));
      cOut.println();
      /*.
      ==========================================================================================
      Create a new XRandom instance initialized without a specified seed value. Then generate a
      60 character length random XString of printable characters in the ASCII character value
      range of from space to tilde [(char)32..(char)126] and print it out. Then generate another
      from the same seeded XRandom instance print it out too. The two sequences of characters
      should be different from one another as well as different from all the ones printed
      earlier.
      ------------------------------------------------------------------------------------------ */
      obj = new XRandom();
      cOut.println(obj.nextAscii(60));
      cOut.println(obj.nextAscii(60));
      cOut.println();
      }



   }  // class XRandom



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