image
 
image
ConsoleStream.java


/*::.
==================================================================================================================================
=================================================¦ Copyright © 2007 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       ConsoleStream.java
Originator: Allen Baker (2007.01.22 21:06)
LayoutRev:  5
================================================================================================================================== */



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



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



/*::
======================================================================================================================== *//**
Instances of this class write messages to the console in a predefined format that is suitable for logging. An instance
writes single-line messages in this format:
   <BLOCKQUOTE>
      <PRE id="unindent">
         2007-01-23 11:12:29:414 --->  This is a single-line console message.
      </PRE>
   </BLOCKQUOTE>

It writes multi-line messages in this format:
   <BLOCKQUOTE>
      <PRE id="unindent">
         2007-01-23 11:50:53:414 --->  ===================================================
                                       ===================================================
                                       This is a wordy, multi-line console message that is
                                       intended to demonstrate word wrapping and multi-line
                                       message boxing.
                                       ---------------------------------------------------
      </PRE>
   </BLOCKQUOTE>

It writes multi-line messages that have a title in this format:
   <BLOCKQUOTE>
      <PRE id="unindent">
         2007-01-23 11:50:53:414 --->  ===================================================
                                       =====================| Title |=====================
                                                            ---------
                                       This is a wordy, multi-line console message that is
                                       intended to demonstrate word wrapping and multi-line
                                       message boxing.
                                       ---------------------------------------------------
      </PRE>
   </BLOCKQUOTE>

It writes multi-line messages that have a multi-line title in this format:
   <BLOCKQUOTE>
      <PRE id="unindent">
         2007-01-23 11:50:53:414 --->  ===================================================
                                       ====|  This is a wordy, multi-line title that  |===
                                       ====| demonstrates how titles are word-wrapped |===
                                       ====|      and centered in the title box.      |===
                                           --------------------------------------------
                                       This is a wordy, multi-line console message that is
                                       intended to demonstrate word wrapping and multi-line
                                       message boxing.
                                       ---------------------------------------------------
      </PRE>
   </BLOCKQUOTE>

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  ConsoleStream  out =
                     (
                     new ConsoleStream().
                     setLineLength(52).
                     setCapitalizer(new UString.BasicEnglishCapitalizer())
                     );

                  XString  s1 =
                     "this is a single line console message.                          \n";

                  XString  s2 =
                     "this is a wordy, multi-lined console message that is intended   \n" +
                     "to demonstrate word wrapping and multi-line message boxing.     \n";

                  XString  t1 =
                     "this is a wordy, multi-line title that demonstrates how titles  \n" +
                     "are word-wrapped and centered in the title box.                 \n";

                  out.println(s1);
                  out.println(s2);
                  out.println("Title",s2);
                  out.println(t1,s2);
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="ConsoleStream.java.html">
               ConsoleStream.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class ConsoleStream
   {



   /*:                                    :METHOD:000:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   The key to creating a singleton is to prevent the client programmer from having any way to create an
   object except the ways you provide. You must make all constructors private, and you must create at
   least one constructor to prevent the compiler from synthesizing a default constructor for you (which
   it will create as “public”).<P>

   At this point, you decide how you’re going to create your object. Here, it’s created statically, but
   you can also wait until the client programmer asks for one and create it on demand. In any case, the
   object should be stored privately. You provide access through public methods. Here, getSingleton()
   produces the reference to the Singleton object. The rest of the interface (println(), printf(),
   etc.) is the regular class interface.

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

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static ConsoleStream getSingleton()
      {
      return cThis;
      }



   /*:                                    :METHOD:001:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows the user to tell this object to shut up. If set to TRUE, this object will stop
   outputting messages that are sent into it via println(), printf(), etc. If set to FALSE, this object
   will start blabbering normally again.

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

   @return
      A reference to this object

   @param
      P is a boolean that tells this object whether or not to be quiet.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream setQuiet(boolean p)
      {
      iQuiet = p;
      return this;
      }



   /*:                                    :METHOD:002:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the line length that will be used for word wrapping.

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

   @return
      A reference to this object

   @param
      pLineLength is the line length that this ConsoleStream will use for word wrapping the message.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream setLineLength(int pLineLength)
      {
      iLineLength = UMath.forceIntoRange
         (
         pLineLength,
         ConsoleMessage.minLineLength(),
         ConsoleMessage.maxLineLength() - STAMP_LENGTH
         );
      return this;
      }



   /*:                                    :METHOD:003:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method resets the line length that will be used for word wrapping to the default length.

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

   @return
      A reference to this object
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream resetLineLength()
      {
      iLineLength = UMath.forceIntoRange
         (
         ConsoleMessage.defaultLineLength(),
         ConsoleMessage.minLineLength(),
         ConsoleMessage.maxLineLength() - STAMP_LENGTH
         );
      return this;
      }



   /*:                                    :METHOD:004:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the capitalizer that will be used for titles and messages.

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

   @return
      A reference to this object

   @param
      pCapitalizer is the Capitalizer that this ConsoleStream will use for titles and messages.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream setCapitalizer(UCapitalizer pCapitalizer)
      {
      iCapitalizer = pCapitalizer;
      return this;
      }



   /*:                                    :METHOD:005:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Prints the XString representation of pStr <B>the next time one of the println() or printf() methods
   is called</B>.<P>

   The XString is stored in a buffer and subsequent print()s are appended to the buffer. The buffer is
   word-wrapped, witten to the console, and flushed the next time one of the println() or printf()
   methods is called.

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

   @param
      pStr is the object to be printed
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream print(Type1 pStr)
      {
      String  str = UString.toString(pStr);
      iStrBuf = iStrBuf.concat(str);
      return this;
      }



   /*:                                    :METHOD:006:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Terminates the current line by writing the line separator XString. The line separator XString is
   defined by the system property line.separator , and is not necessarily a single newline character (
   '\n' ).

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

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream println()
      {
      XString  ttl = new XString("");
      XString  msg = new XString("");
      return this.println(ttl,msg);
      }



   /*:                                    :METHOD:007:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Prints a message and then terminates the line. This method behaves as though it invokes {@link
   #print(XString)} and then {@link #println()}
.

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

   @param
      pMsg is the message to be printed
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream println(Type1 pMsg)
      {
      XString  ttl = new XString("");
      XString  msg = new XString(pMsg);
      return this.println(ttl,msg);
      }



   /*:                                    :METHOD:008:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Prints a message with a title and then terminates the line. This method behaves as though it invokes
   {@link #print(XString)} and then {@link #println()}
.

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

   @param
      pTitle is the title to be printed
   @param
      pMsg is the message to be printed
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1,Type2> ConsoleStream println(Type1 pTitle, Type2 pMsg)
      {
      /*.
      ==========================================================================================
      This is where the title that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  ttl = new XString(pTitle);
      /*.
      ==========================================================================================
      This is where the message that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  msg = new XString("");
      /*.
      ==========================================================================================
      Add the print() buffer content to the message that is to be word wrapped and printed and
      then flush the buffer.
      ------------------------------------------------------------------------------------------ */
      msg = this.appendAndFlushPrintBuffer(msg);
      /*.
      ==========================================================================================
      Now add the message that was passed in to this method.
      ------------------------------------------------------------------------------------------ */
      msg = msg.concat(pMsg);
      /*.
      ==========================================================================================
      Turn the message and title into a word-wrap console message.
      ------------------------------------------------------------------------------------------ */
      ArrayList<XString>  xStrAL =
         (
         new ConsoleMessage(ttl,msg).
            setLineLength(iLineLength).
               setWordWrap(iWordWrap).
                  reduceMaxLineLength(STAMP_LENGTH).
                     setCapitalizer(iCapitalizer).
                        lines()
         );
      /*.
      ==========================================================================================
      Turn the message and title into a single word-wrapped XString and send out for printing.
         What is the reason for converting it to one big XString and sending that to print
         instead of just iterating through the array of lines and printing each in turn? I
         wanted to make this code leveragable to a threaded version of a console stream. In that
         case, printing each line separately would have to be synchronized to prevent the
         possibility of multiple messages being interleaved together in the output stream. It
         would be better to synchronize access to a queue into which each message is placed in
         its entirety and from which a printing thread would retreived each subsequent message
         for printing.
      ------------------------------------------------------------------------------------------ */
      msg = this.convertToXString(xStrAL);
      this.printMessage(msg);
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return this;
      }



   /*:                                    :METHOD:009:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString to this output stream using the specified format
   xString and arguments.

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

   @return
      This output stream

   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream printf(Type1 format, Object... args) throws Exception
      {
      XString  ttl = new XString("");
      XString  fmt = new XString(format);
      return this.titledPrintf(ttl,fmt,args);
      }



   /*:                                    :METHOD:010:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString to this output stream using the specified format
   xString and arguments.

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

   @return
      This output stream

   @param
      pSeverity is the severity code to convert to a XString representation and prepend to the message.
   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream printfWithSeverity(int pSeverity, Type1 format, Object... args) throws Exception
      {
      XString  ttl = new XString("");
      XString  fmt = new XString(format);
      fmt = Const.code2XStr(pSeverity).concat(":  ").concat(fmt);
      return this.titledPrintf(ttl,fmt,args);
      }



   /*:                                    :METHOD:011:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString with a title to this output stream using the
   specified format XString and arguments.

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

   @return
      This output stream

   @param
      pTitle is the title to be printed
   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1,Type2> ConsoleStream titledPrintf(Type1 pTitle, Type2 format, Object... args) throws Exception
      {
      /*.
      ==========================================================================================
      This is where the title that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  ttl = new XString(pTitle);
      /*.
      ==========================================================================================
      This is where the message that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  msg = new XString("");
      /*.
      ==========================================================================================
      Add the print() buffer content to the message that is to be word wrapped and printed and
      then flush the buffer.
      ------------------------------------------------------------------------------------------ */
      msg = this.appendAndFlushPrintBuffer(msg);
      /*.
      ==========================================================================================
      Now add the message that was passed in to this method.
      ------------------------------------------------------------------------------------------ */
      XString  fmt = XString.toXString(format);
      msg = msg.concat((new Formatter()).format(fmt.string(),args).out().toString());
      /*.
      ==========================================================================================
      Turn the message and title into a word-wrap console message.
      ------------------------------------------------------------------------------------------ */
      ArrayList<XString>  xStrAL =
         (
         new ConsoleMessage(ttl,msg).
            setLineLength(iLineLength).
               setWordWrap(iWordWrap).
                  reduceMaxLineLength(STAMP_LENGTH).
                     setCapitalizer(iCapitalizer).
                        lines()
         );
      /*.
      ==========================================================================================
      Turn the message and title into a single word-wrapped XString and send out for printing.
         What is the reason for converting it to one big XString and sending that to print
         instead of just iterating through the array of lines and printing each in turn? I
         wanted to make this code leveragable to a threaded version of a console stream. In that
         case, printing each line separately would have to be synchronized to prevent the
         possibility of multiple messages being interleaved together in the output stream. It
         would be better to synchronize access to a queue into which each message is placed in
         its entirety and from which a printing thread would retreived each subsequent message
         for printing.
      ------------------------------------------------------------------------------------------ */
      msg = this.convertToXString(xStrAL);
      this.printMessage(msg);
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return this;
      }



   /*:                                    :METHOD:012:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString with a title to this output stream using the
   specified format XString and arguments.

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

   @return
      This output stream

   @param
      pTitle is the title to be printed
   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream banner(Type1 pTitle) throws Exception
      {
      /*.
      ==========================================================================================
      This is where the title that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  ttl = new XString(pTitle);
      /*.
      ==========================================================================================
      Turn the message and title into a word-wrap console message.
      ------------------------------------------------------------------------------------------ */
      ArrayList<XString>  xStrAL =
         (
         new ConsoleMessage(ttl,"").
            setLineLength(iLineLength).
               reduceMaxLineLength(STAMP_LENGTH).
                  setCapitalizer(iCapitalizer).
                     banner()
         );
      /*.
      ==========================================================================================
      This is where the message that will be word-wrapped and printed is stored.
      ------------------------------------------------------------------------------------------ */
      XString  msg = new XString("");
      msg = this.convertToXString(xStrAL);
      this.printMessage(msg);
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return this;
      }



   /*:                                    :METHOD:013:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Prints a message and then terminates the line. This method behaves as though it invokes {@link
   #print(XString)} and then {@link #println()}
.

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

   @param
      pSeverity is the severity code to convert to a XString representation and prepend to the message.
   @param
      pMsg is the message to be printed
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream println(int pSeverity, Type1 pMsg)
      {
      XString  msg = Const.code2XStr(pSeverity).concat(":  ").concat(pMsg);
      return this.println(msg);
      }



   /*:                                    :METHOD:014:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   Prints a message with a title and then terminates the line. This method behaves as though it invokes
   {@link #print(XString)} and then {@link #println()}
.

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

   @param
      pSeverity is the severity code to convert to a XString representation and prepend to the message.
   @param
      pTitle is the title to be printed
   @param
      pMsg is the message to be printed
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1,Type2> ConsoleStream println(int pSeverity, Type1 pTitle, Type2 pMsg)
      {
      XString  ttl = new XString(pTitle);
      XString  msg = Const.code2XStr(pSeverity).concat(":  ").concat(pMsg);
      return this.println(ttl,msg);
      }



   /*:                                    :METHOD:015:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString to this output stream using the specified format
   xString and arguments.

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

   @return
      This output stream

   @param
      pSeverity is the severity code to convert to a XString representation and prepend to the message.
   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream severityPrintf(int pSeverity, Type1 format, Object... args) throws Exception
      {
      XString  fmt = XString.toXString(format);
      XString  msg =
         (
         Const.code2XStr(pSeverity).
            concat(":  ").
               concat
                  (
                  (new Formatter()).format(fmt.string(),args).out().toString()
                  )
         );
      return this.println(msg);
      }



   /*:                                    :METHOD:016:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   A convenience method to write a formatted XString with a title to this output stream using the
   specified format XString and arguments.

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

   @return
      This output stream

   @param
      pSeverity is the severity code to convert to a XString representation and prepend to the message.
   @param
      pTitle is the title to be printed
   @param
      Format A format XString as described in <A href="../util/Formatter.html#syntax">Format XString
      syntax
      </A>
   @param
      Args Arguments referenced by the format specifiers in the format XString. If there are more
      arguments than format specifiers, the extra arguments are ignored. The number of arguments is
      variable and may be zero. The maximum number of arguments is limited by the maximum dimension of
      a Java array as defined by the <A href="http://java.sun.com/docs/books/vmspec/">Java Virtual
      Machine Specification</A>. The behaviour on a <TT>null</TT> argument depends on the <a
      href="../util/Formatter.html#syntax">conversion</A>.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1,Type2> ConsoleStream titledSeverityPrintf(int pSeverity, Type1 pTitle, Type2 format, Object... args) throws Exception
      {
      XString  fmt = XString.toXString(format);
      XString  ttl = new XString(pTitle);
      XString  msg =
         (
         Const.code2XStr(pSeverity).
            concat(":  ").
               concat
                  (
                  (new Formatter()).format(fmt.string(),args).out().toString()
                  )
         );
      return this.println(ttl,msg);
      }



   /*:                                    :METHOD:017:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method causes the ConsoleStream to also be written to a file.

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

   @return
      A reference to this object

   @param
      pLogFileName is the name of the log file to which this objects copies its output.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1> ConsoleStream startLog(Type1 pLogFileName) throws Exception
      {
      iLogFile = new TextWriter(pLogFileName);
      return this;
      }



   /*:                                    :METHOD:018:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method causes the ConsoleStream to stop being written to a file.

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

   @return
      A reference to this object
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream stopLog()
      {
      if (iLogFile != null)
         {
         iLogFile.println();
         iLogFile.flush();
         iLogFile.close();
         iLogFile = null;
         }
      return this;
      }



   /*:                                    :METHOD:019:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows the user to turn word wrapping on and off. By default, word wrapping is ON.

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

   @return
      A reference to this object

   @param
      pWordWrap is true if word wrapping is to be ON, false if it is to be OFF.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream pushWordWrap(boolean pWordWrap)
      {
      iWrapStack.push(iWordWrap);
      iWordWrap = pWordWrap;
      return this;
      }



   /*:                                    :METHOD:020:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows the user to restore word wrapping to whatever it was before the last
   pushWordWrap() call.

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

   @return
      A reference to this object
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream popWordWrap()
      {
      if (iWrapStack.size() > 0)
         {
         iWordWrap = iWrapStack.pop();
         }
      return this;
      }



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

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

   @return
      A reference to this object

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



   /*:                                    :METHOD:022: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="ConsoleStream.java.html#022">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public ConsoleStream test() throws Exception
      {
      this.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
      <BLOCKQUOTE>
         <PRE id="unindent">
            CLASS_NAME    : the name of this class
            DFLT_LINE_LEN : the default line length for word wrapping
            STAMP_FORMAT  : the format XString for formatting time stamps.
            STAMP_PAD     : a XString of blanks that is the same length as a time
                            stamp.
            STAMP_LENGTH  : the length of a time stamp.
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private static final XString  CLASS_NAME    = new XString(ConsoleStream.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();
   private static final XString  STAMP_FORMAT  = new XString("yyyy-MM-dd HH:mm:ss:SSS --->  ");
   private static final XString  STAMP_PAD     = new XString("                              ");
   private static final int      STAMP_LENGTH  = STAMP_FORMAT.length();
   /*.
   ==========================================================================================
   Class variables
      <BLOCKQUOTE>
         <PRE id="unindent">
            cThis : is a singleton that is created here statically.
            cOut  : console output.
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cThis = new ConsoleStream();
   private static ConsoleStream  cOut  = ConsoleStream.getSingleton();
   /*.
   ==========================================================================================
   Instance variables
      <BLOCKQUOTE>
         <PRE id="unindent">
            iWrapStack    : allows pushing and popping of word wrap state
            iWordWrap     : current word wrapping state (on or off)
            iQuiet        : tells this object whether or not to print
            iStrBuf       : a buffer where print() strings are accumulated
                            before being printed and flushed by the next call
                            to a println() or printf() method.
            iLineLength   : the line length for word wrapping
            iCapitalizer  : the capitalizer used by the word wrapper
            iLastWasBoxed : flag that remembers if the last msg output was
                            multi-lined (therefor, boxed).
            iLogFile      : if logging to a file was requested, this is the file
                            that the log messages are being written to.
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private Stack<Boolean>  iWrapStack    = new Stack<Boolean>();
   private boolean         iWordWrap     = true;
   private boolean         iQuiet        = false;
   private String          iStrBuf       = "";
   private int             iLineLength   = ConsoleMessage.defaultLineLength();
   private UCapitalizer    iCapitalizer  = null;
   private boolean         iLastWasBoxed = false;
   private TextWriter      iLogFile      = null;



   /*:                                    :METHOD:023:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a ConsoleStream class object.<P>

   The key to creating a singleton is to prevent the client programmer from having any way to create an
   object except the ways you provide. You must make all constructors private, and you must create at
   least one constructor to prevent the compiler from synthesizing a default constructor for you (which
   it will create as “public”).<P>

   At this point, you decide how you’re going to create your object. Here, it’s created statically, but
   you can also wait until the client programmer asks for one and create it on demand. In any case, the
   object should be stored privately. You provide access through public methods. Here, getSingleton()
   produces the reference to the Singleton object. The rest of the interface (println(), printf(),
   etc.) is the regular class interface.

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

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private ConsoleStream()
      {
      this.resetLineLength();
      }



   /*:                                    :METHOD:024:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method concatenates the print() buffer to pMsg and then flushes the buffer.

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

   @return
      An XString containing pMsg with the content of the print() buffer concatenated to it.

   @param
      pMsg is the XString to which the content of the print() buffer is concatenated.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString appendAndFlushPrintBuffer(XString pMsg)
      {
      pMsg    = pMsg.concat(iStrBuf);
      iStrBuf = "";
      return pMsg;
      }



   /*:                                    :METHOD:025:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method converts an ArrayList of XStrings into a single XString. This is the method that puts a
   single timestamp on each message.<P>

   What is the reason for converting it to one big XString and sending that to print instead of just
   iterating through the array of lines and printing each in turn? I wanted to make this code
   leveragable to a threaded version of a console stream. In that case, printing each line separately
   would have to be synchronized to prevent the possibility of multiple messages being interleaved
   together in the output stream. It would be better to synchronize access to a queue into which each
   message is placed in its entirety and from which a printing thread would retreived each subsequent
   message for printing.

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

   @return
      The new XString.

   @param
      pArrayList is the ArrayList of XStrings to convert into a single XString.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString convertToXString(ArrayList<XString> pArrayList)
      {
      /*.
      ==========================================================================================
      Start with a time stamp for this message
      ------------------------------------------------------------------------------------------ */
      XString  timeStamp = new XString(Util.timeStamp(STAMP_FORMAT));

      XString  eoln      = new XString("\n");
      boolean  stamped   = false;
      /*.
      ==========================================================================================
      Now catenate the message lines. The time stamp only goes on the first line of the message.
      ------------------------------------------------------------------------------------------ */
      XString  result = new XString("");
      for (XString xStr : pArrayList)
         {
         result = result.concat((stamped)? STAMP_PAD : timeStamp);
         result = result.concat(xStr);
         result = result.concat(eoln);
         stamped = true;
         }
      /*.
      ==========================================================================================
      Strip off the last eoln because println() is going to be used to print and it will
      terminate the XString with its own eoln.
      ------------------------------------------------------------------------------------------ */
      result = result.trimRight(eoln);
      return result;
      }



   /*:                                    :METHOD:026:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method does the actual printing of pMsg. This is the method that sets off boxed messages by
   placing a blank line between every boxed message and any message before or after it.

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

   @param
      pMsg is the message to print.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private void printMessage(XString pMsg)
      {
      boolean  boxed = this.isBoxed(pMsg);
      if (boxed || iLastWasBoxed)
         {
         if ( ! iQuiet)
            {
            System.out.println();
            }
         if (iLogFile != null)
            {
            iLogFile.println();
            }
         }
      iLastWasBoxed = boxed;
      if ( ! iQuiet)
         {
         System.out.println(pMsg);
         }
      if (iLogFile != null)
         {
         iLogFile.println(pMsg);
         }
      }



   /*:                                    :METHOD:027:BOOKMARK:
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method figures out if pMsg is a boxed (multi-lined) message.

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

   @returns
      True if pMsg is boxed, false otherwise.

   @param
      pMsg is the message to check.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private boolean isBoxed(XString pMsg)
      {
      return(pMsg.indexOf('\n') > 0);
      }



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



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



   /*:                                    :METHOD:028: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.ConsoleStream
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="ConsoleStream.java.html#028">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);
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      cOut.test();
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      XString  s1 = new XString
         (
         "this is a single-line console message.                          \n"
         );

      XString  s2 = new XString
         (
         "this is a wordy, multi-line console message that is intended    \n" +
         "this is a wordy, multi-line console message that is intended    \n" +
         "this is a wordy, multi-line console message that is intended    \n" +
         "this is a wordy, multi-line console message that is intended    \n" +
         "to demonstrate word wrapping and multi-line message boxing.     \n"
         );

      XString  s3 = new XString
         (
         "<B>Example usage:</B><PRE>\n" +
         "*   // ===============================================\n" +
         "*   // copy to sysout the names of all the files that match the file\n" +
         "*   // specifier - \"/test/testin/*.iwa\".\n" +
         "*   // -----------------------------------------------\n" +
         "*      FileNameList a    = new FileNameList(\"/test/testin/*.iwa\");\n" +
         "*      Iterator     iter = a.iterator();\n" +
         "*\n" +
         "*      System.out.println(\"<\" + a.getDirectoryName() + \"><\" + a.getFileNamePattern() + \">\");\n" +
         "*      while (iter.hasNext())\n" +
         "*         {\n" +
         "*         System.out.println(iter.next());\n" +
         "*         }\n" +
         "</PRE>\n"
         );

      XString  t1 = new XString
         (
         "this is a wordy, multi-line title that demonstrates how titles  \n" +
         "this is a wordy, multi-line title that demonstrates how titles  \n" +
         "this is a wordy, multi-line title that demonstrates how titles  \n" +
         "this is a wordy, multi-line title that demonstrates how titles  \n" +
         "are word-wrapped and centered in the title box.                 \n"
         );

      cOut.println(1,s1);
      cOut.println(2,s2);
      cOut.println(3,"Title",s2);
      cOut.println(4,t1,s2);

      cOut.severityPrintf(4,"%s",s2);

      cOut.println();
      cOut.println();
      cOut.println();

      cOut.print("print() buffering test:  ");
      cOut.print("this is a test ");
      cOut.print("of the emergency broadcast system. ");
      cOut.print("In the event ");
      cOut.print("of an actual emergency, you would ");
      cOut.print("have heard an important ");
      cOut.print("message following that annoying tone. ");
      cOut.println("- THE END");

      cOut.pushWordWrap(false);
      cOut.println(s3);
      cOut.popWordWrap();
      cOut.println(s3);
      cOut.pushWordWrap(false);
      cOut.println("title",s3);
      cOut.popWordWrap();
      cOut.println("title",s3);

      }



   }  // class ConsoleStream



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