/*::.
==================================================================================================================================
=================================================� Copyright � 2007 Allen Baker �=================================================
                                                 +------------------------------+
File:       XProperties.java
Originator: Allen Baker (2007.05.27 19:30)
LayoutRev:  5
================================================================================================================================== */



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



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



/*::
======================================================================================================================== *//**
This class extends the capabilities of the Properties class.<P>

Instances of this class are persistent sets of properties that are loaded from a file.<P>

Each XProperties object is loaded by reading a property list (key and element pairs) from a file. The file is assumed to
be using the ISO 8859-1 character encoding. Every property occupies one line of the file. Each line is terminated by a
line terminator (\n or \r or \r\n). Lines from the file are processed until the end of file is reached on the file.<P>

A line that contains only whitespace or whose first non-whitespace character is an ASCII # is ignored (thus, # indicate
comment lines).<P>

Every line other than a blank line or a comment line describes one property to be added to the table (except that if a
line ends with \, then the following line, if it exists, is treated as a continuation line, as described below). The key
consists of all the characters in the line starting with the first non-whitespace character and up to, but not
including, the first ASCII =, :, or whitespace character. All of the key termination characters may be included in the
key by preceding them with a \. Any whitespace after the key is skipped; if the first non-whitespace character after the
key is = or :, then it is ignored and any whitespace characters after it are also skipped. All remaining characters on
the line become part of the associated element XString. Within the element XString, the ASCII escape sequences \t, \n,
\r, \\, \", \', \ (a backslash and a space), and \\uxxxx are recognized and converted to single characters. Moreover, if
the last character on the line is \, then the next line is treated as a continuation of the current line; the \ and line
terminator are simply discarded, and any leading whitespace characters on the continuation line are also discarded and
are not part of the element XString.<P>

As an example, each of the following four lines specifies the key "Truth" and the associated element value "Beauty":
   <BLOCKQUOTE>
      <PRE id="unindent">
         Truth = Beauty
            Truth:Beauty
         Truth       :Beauty
      </PRE>
   </BLOCKQUOTE>

In another example, the following three lines specify a single property:
   <BLOCKQUOTE>
      <PRE id="unindent">
         fruits            apple, banana, pear, \
                                           cantaloupe, watermelon, \
                                           kiwi, mango
      </PRE>
   </BLOCKQUOTE>

The key is "fruits" and the associated element is:
   <BLOCKQUOTE>
      <PRE id="unindent">
         "apple, banana, pear, cantaloupe, watermelon,kiwi, mango"
      </PRE>
   </BLOCKQUOTE>

Note that a space appears before each \ and consequently a space appears after the commas following "pear" and
"watermelon" in the final result. The \ itself, the [invisible] line terminator, and the leading whitespace on the
continuation line are all discarded.<P>

Finally, a third example, the lines:
   <BLOCKQUOTE>
      <PRE id="unindent">
         cheese
         crackers =
      </PRE>
   </BLOCKQUOTE>

Specify that the keys are "cheese" and "crackers" and the associated element is the empty String for both "cheese" and
"crackers".

<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="XProperties.java.html">
               xProperties.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class XProperties extends Properties
   {



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a XProperties object and loads it by reading a property list (key and element
   pairs) from the specified file.

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

   @param
      pFile is the File to read the properties from
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XProperties(File pFile) throws IOException
      {
      BufferedInputStream mStream = new BufferedInputStream
         (
         new FileInputStream(pFile)
         );
      load(mStream);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates a XProperties object and loads it by reading a property list (key and element
   pairs) from the specified file.

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

   @param
      pFileName is the name of the file to read the properties from
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type> XProperties(Type pFileName) throws IOException
      {
      BufferedInputStream mStream = new BufferedInputStream
         (
         new FileInputStream(UString.toString(pFileName))
         );
      load(mStream);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method writes all the properties to the ConsoleStream

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

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public void printList()
      {
      printList("");
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method writes all the properties to the ConsoleStream along with a title XString

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

   @param
      pTitle is a title sting that is places at the top of the list.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type> void printList(Type pTitle)
      {
      /*.
      ==========================================================================================
      Figure out how long the longest property name is
      ------------------------------------------------------------------------------------------ */
      Set       propKeys = keySet();
      int       maxLen   = 0;
      Iterator  iter     = propKeys.iterator();
      while (iter.hasNext())
         {
         String propertyName = (String)iter.next();
         maxLen = UMath.max(maxLen,propertyName.length());
         }
      /*.
      ==========================================================================================
      Get each property name and its value
      ------------------------------------------------------------------------------------------ */
      int  i = 0;
      iter = propKeys.iterator();
      while (iter.hasNext())
         {
         /*.
         ==========================================================================================
         Print the property an its value
         ------------------------------------------------------------------------------------------ */
         String propertyName  = (String)iter.next();
         String propertyValue = getProperty(propertyName);
         while (propertyName.length() < maxLen)
            {
            propertyName += " ";
            }
         cOut.print(propertyName + " = " + propertyValue + "\n");
         }
      }



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

   <P><B>Implementation: </B><A HREF="XProperties.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 XProperties 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="XProperties.java.html#005">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public XProperties 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(XProperties.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.XProperties
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="XProperties.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
      ------------------------------------------------------------------------------------------ */
      XProperties  obj = new XProperties("/temp/test.prop");
      /*.
      ==========================================================================================
      Test code
      ------------------------------------------------------------------------------------------ */
      obj.test();
      obj.printList("IwaLoader.properties");
      }



   }  // class XProperties



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