/*
 * @(#)ConsoleGateway.java   2.5.0   1 September 2006
 *
 * Copyright 2006
 * College of Computer and Information Science
 * Northeastern University
 * Boston, MA  02115
 *
 * The Java Power Tools software may be used for educational
 * purposes as long as this copyright notice is retained intact
 * at the top of all source files.
 *
 * To discuss possible commercial use of this software, 
 * contact Richard Rasala at Northeastern University, 
 * College of Computer and Information Science,
 * 617-373-2462 or rasala@ccs.neu.edu.
 *
 * The Java Power Tools software has been designed and built
 * in collaboration with Viera Proulx and Jeff Raab.
 *
 * Should this software be modified, the words "Modified from 
 * Original" must be included as a comment below this notice.
 *
 * All publication rights are retained.  This software or its 
 * documentation may not be published in any media either
 * in whole or in part without explicit permission.
 *
 * This software was created with support from Northeastern 
 * University and from NSF grant DUE-9950829.
 */

package edu.neu.ccs.console;

import edu.neu.ccs.*;
import edu.neu.ccs.filter.*;
import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;
import edu.neu.ccs.gui.*;

import java.awt.*;
import java.beans.*;
import java.io.*;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.text.ParseException;
import javax.swing.event.SwingPropertyChangeSupport;

/**
 * <P>Provides methods for using a console object
 * to perform text input and output operations.
 *
 * An instance of this class uses the standard system streams,
 * <CODE>System.in</CODE>, <CODE>System.out</CODE>, 
 * and <CODE>System.err</CODE> by default, 
 * but can be "activated".
 *
 * An "activated" console is a separate floating window 
 * that displays text output and gathers text input
 * using functionality not provided by the system streams.
 *
 * As some Java Virtual Machines restrict access
 * to the system streams through use of a security manager,
 * an instance of this class may be the only way
 * to provide a text console for an applet or application.</P>
 *
 * <P>It is not safe to call methods of this class
 * on the event handling thread, regardless of whether or not
 * the console is activated.
 *
 * In addition to length calculations, all modal input operations,
 * such as the ones provided by this class,
 * should be performed on the main thread or a user thread
 * and never the event-handling thread.</P>
 *
 * <P>The functionality of this class is based on 
 * the principles of the C++ tools provided in 
 * <CODE>"IOTools"</CODE> by Richard Rasala of the
 * Northeastern University College of Computer Science.</P>
 *
 * @author  Richard Rasala
 * @author  Jeff Raab
 * @version 2.5.0
 */
public class ConsoleGateway
    implements ConsoleInputListener, JPTConstants, Serializable 
{
    /** Constant index for the output stream. */
    private static final int OUT = 0;
                                
    /** Constant index for the error stream. */
    private static final int ERR = 1;
                                
    /** Constant index for the input stream. */
    private static final int IN  = 2;
                                
    /** Bound property name for the activated property. */
    public static final String ACTIVATED = "activated";

    /** Bound property name for the input color property. */
    public static final String INPUT_COLOR = "input.color";

    /** Bound property name for the output color property. */
    public static final String OUTPUT_COLOR = "output.color";

    /** Bound property name for the error color property. */
    public static final String ERROR_COLOR = "error.color";

    /** Helper object for property change API. */
    protected SwingPropertyChangeSupport changeAdapter = 
        new SwingPropertyChangeSupport(this);

    /** Case action filter used by this console object. */
    protected CaseActionFilter action = null;

    // The following data member is shared between 
    // the user thread and the event dispatch thread 
    // for an activated console, through use of the
    // ConsoleInputListener interface
    
    /** Input text last gathered by this console object. */
    protected String input = "";
    
    /** 
     * The input stream used by this console object
     * as the default "in" stream. 
     */
    protected transient InputStream inStream = null;
    
    /** 
     * The output streams used by this console object
     * as the default "out" and "err" streams. 
     */
    protected transient OutputStream[] outStreams = null;
    
    /** 
     * The end-of-line sequence 
     * for the operating system on which 
     * the Java Virtual Machine is running.
     */
    protected transient String endl = null;
    
    /** 
     * The console window to use for visualization
     * of this console object.
     *
     * If <CODE>null</CODE>, input and output operations 
     * are performed using the default stream objects.
     */
    protected ConsoleWindow window = null;
    
    //  ConsoleInputStream is an inner class defined below
    
    /** 
     * The virtual stream object
     * providing text input functionality. 
     */
    public ConsoleInputStream in = new ConsoleInputStream();

    //  ConsoleOutputStream is an inner class defined below
    
    /** 
     * The virtual stream object 
     * providing text output functionality. 
     */
    public PrintStream out = new PrintStream(
        new ConsoleOutputStream(OUT));
    
    /** 
     * The virtual stream object 
     * providing error text output functionality. 
     */
    public PrintStream err = new PrintStream(
        new ConsoleOutputStream(ERR));
    
    //////////////////
    // Constructors //
    //////////////////
    
    /**
     * Constructs a console object using the system streams
     * by default for input and output operations. 
     *
     * It is not necessary to directly call this constructor,
     * unless interested in creating a console object
     * for specific individual use.  
     *
     * For access to the shared console object, implement the 
     * <CODE>{@link ConsoleAware ConsoleAware}</CODE>
     * interface and use the console object reference
     * that interface makes accessible.
     *
     * @see ConsoleAware
     */
    public ConsoleGateway() {
        inStream = System.in;
        outStreams = new OutputStream[] {System.out, System.err};
        endl = SystemUtilities.getLineSeparator();
    }

    //////////////////////////
    // ConsoleInputListener //
    //////////////////////////
    
    /**
     * Handles input gathered from an "activated" console window.
     *
     * @param text the input text gathered from the stream
     */
    public synchronized void consoleInputPerformed(String text) {
        input = text.substring(0, text.indexOf(endl));

        // note: wait is possibly called in the getOneLine method
        notify();
    }

    ////////////////
    // Public API //
    ////////////////

    /**
     * Prints a prompt to the text output stream
     * that is followed by a single space, 
     * but no line separator sequence.
     *
     * If the prompt text is <CODE>null</CODE> 
     * or is the empty <CODE>String</CODE>,
     * this method does nothing.
     * 
     * @param text the prompt <CODE>String</CODE> to display
     * @see #prompt(String, String)
     */
    public synchronized void prompt(String text) {
        if ((text != null) && (text.length() > 0))
            out.print(text + " ");
    }
   
    /**
     * Prints a prompt to the text output stream
     * that is followed by a single space
     * and a default text response in square brackets, 
     * but no line separator sequence.
     * 
     * If the prompt text is <CODE>null</CODE> 
     * or is the empty <CODE>String</CODE>,
     * the prompt portion will be omitted from the output.
     *
     * If the default response is <CODE>null</CODE> 
     * or is the empty <CODE>String</CODE>
     * the response portion will be omitted from the output.
     *
     * @param text the prompt <CODE>String</CODE> to display
     * @param response the default response text
     * @see #prompt(String)
     */
    public synchronized void prompt(String text, String response) {
        prompt(text);
        
        if ((response != null) && (response.length() > 0))
            out.print("[" + response + "] ");
    }
    
    /**
     * Prints a default prompt to the text output stream
     * for the user to press the Return key, 
     * and pauses the current thread
     * until the user presses the key.
     * 
     * @see #pressReturn(String)
     */
    public synchronized void pressReturn() {
        pressReturn(null);
    }

    /**
     * Prints the given prompt to the text output stream
     * and pauses the current thread
     * until the user presses the key.
     * 
     * @param prompt the prompt <CODE>String</CODE> to display
     * @see #pressReturn()
     */
    public synchronized void pressReturn(String prompt) {
  
        // caller message
        if ((prompt != null) && (prompt.length() > 0))
            out.println(prompt);
  
        // standard message
        prompt("Press return to continue");
  
        // wait for and then ignore next line of input
        getOneLine();
    }

    /**
     * Prints the given prompt to the text output stream
     * and pauses the current running thread 
     * until the user inputs "<CODE>Y[es]</CODE>" 
     * or "<CODE>N[o]</CODE>".
     * 
     * @param prompt the prompt <CODE>String</CODE> to display
     * @param response the default response to the confirmation:
     *        <CODE>true</CODE> for "<CODE>Y[es]</CODE>" or
     *      <CODE>false</CODE> for "<CODE>N[o]</CODE>
     * @return <CODE>true if the user input "<CODE>Y[es]</CODE>"
     *         or <CODE>false</CODE> if the user input
     *      "<CODE>N[o]</CODE>"
     */
    public synchronized boolean confirm(
        String prompt, 
        boolean response) 
    {

        // set default as string
        String responseString = response ? "Y" : "N";
  
        // define reply string
        String reply = "";
  
        // loop until user choice is clear
        while (true) {
            reply = in.demandString(prompt, responseString);
    
            // accept the default response if no input provided
            if (reply.length() == 0) 
                break;

            // store a response of "Y[es]"
            if (Character.toUpperCase(reply.charAt(0)) == 'Y') {
                response = true;
                break;
            }
            
            // store a response of "N[o]"
            if (Character.toUpperCase(reply.charAt(0)) == 'N') {
                response = false;
                break;
            }
            
            // otherwise demand clarification
            out.println("Must answer Y[es] or N[o].");
            out.println();
        }
        
        return response;
    }

    /**
     * Sets the current case action filter 
     * for this console object
     * to the given case action filter.
     *
     * If <CODE>null</CODE>, no case action filter
     * will be used by this console object.
     * 
     * @param filter the desired case action filter
     * @see #getCaseActionFilter()
     */
    public synchronized void setCaseActionFilter(CaseActionFilter filter) {
        action = filter;
    }

    /**
     * Returns the current case action filter
     * used by this console object, or <CODE>null</CODE>,
     * if no case action filter is used by this console object.
     * 
     * @see #setCaseActionFilter(CaseActionFilter)
     */
    public synchronized CaseActionFilter getCaseActionFilter() {
        return action;
    }

    /**
     * Sets whether or not this console object is "activated".
     *
     * An "activated" console is a separate floating window 
     * that displays text output and gathers text input
     * using functionality not provided by the system streams.
     *
     * @param isActivated whether or not this console object 
     *      is "activated"
     * @see #isActivated()
     */
    public synchronized void setActivated(boolean isActivated) {
        boolean oldActivated = isActivated();
        
        // build a new console window if necessary
        if (isActivated && !isActivated()) {
            window = new ConsoleWindow();
            window.setVisible(true);
            window.setLocation(WEST);
        }
        
        // remove the current console window if necessary
        else if (!isActivated && isActivated()) {
            ConsoleWindow temp = window;
            window = null;
            temp.close();
        }
        
        // if the activated property has changed
        if (isActivated() != oldActivated) {
        
            // notify listeners of property change
            changeAdapter.firePropertyChange(
                ACTIVATED,
                oldActivated,
                isActivated());
        }
    }

    /**
     * Returns whether or not the console has been "activated".
     *
     * An "activated" console is a separate floating window 
     * that displays text output and gathers text input
     * using functionality not provided by the system streams.
     *
     * @see #setActivated(boolean)
     */
    public synchronized boolean isActivated() {
        return window != null;
    }        
    
    /**
     * <p>If the console is activated then
     * set the console window to its normal state.</p>
     */
    public void normal() {
        if (window != null)
            window.normal();
    }
    
    
    /**
     * <p>If the console is activated then
     * set the console window to its iconified state.</p>
     */
    public void iconify() {
        if (window != null)
            window.iconify();
    }
    
    
    /**
     * <p>If the console is activated then
     * set the console window to its maximized state.</p>
     */
    public void maximize() {
        if (window != null)
            window.maximize();
    }
    
    
    /**
     * <p>If the console is activated then
     * if the current state of the console is not normal,
     * then make it normal otherwise iconify the console.</p>
     */
    public void toggle() {
        if (window != null)
            window.toggle();
    }
    
    
    /**
     * Sets the color used to render input text
     * to the given color.
     *
     * This operation only affects an "activated" console.
     *
     * @param input the desired input color
     * @see #getInputColor()
     */
    public synchronized void setInputColor(Color input) {
        if (isActivated()) {
            Color oldColor = getInputColor();

            window.setInputColor(input);

            changeAdapter.firePropertyChange(
                INPUT_COLOR,
                oldColor,
                getInputColor());
        }
    }

    /**
     * Returns the color used to render input text.
     *
     * This color only affects an "activated" console.
     *
     * @see #setInputColor(Color)
     */
    public synchronized Color getInputColor() {
        if (isActivated())
            return window.getInputColor();
        
        return null;
    }

    /**
     * Sets the color used to render output text
     * to the given color.
     *
     * This operation only affects an "activated" console.
     *
     * @param output the desired output color
     * @see #getOutputColor()
     */
    public synchronized void setOutputColor(Color output) {
        if (isActivated()) {
            Color oldColor = getOutputColor();

            window.setOutputColor(output);

            changeAdapter.firePropertyChange(
                OUTPUT_COLOR,
                oldColor,
                getOutputColor());
        }
    }

    /**
     * Returns the color used to render output text.  
     *
     * This color only affects an "activated" console.
     *
     * @see #setOutputColor(Color)
     */
    public synchronized Color getOutputColor() {
        if (isActivated())
            return window.getOutputColor();
            
        return null;
    }

    /**
     * Sets the color used to render error text
     * to the given color.
     *
     * This operation only affects an "activated" console.
     *
     * @param error the desired error color
     * @see #getErrorColor()
     */
    public synchronized void setErrorColor(Color error) {
        if (isActivated()) {
            Color oldColor = getErrorColor();

            window.setErrorColor(error);

            changeAdapter.firePropertyChange(
                ERROR_COLOR,
                oldColor,
                getErrorColor());
        }
    }

    /**
     * Returns the color used to render error text.  
     *
     * This color only affects an "activated" console.
     *
     * @see #setErrorColor(Color)
     */
    public synchronized Color getErrorColor() {
        if (isActivated())
            return window.getErrorColor();
            
        return null;
    }

    /**
     * Sets the color for each 
     * of the three console text streams 
     * to black.
     *
     * @see #selectColorTextScheme()
     * @see #setOutputColor(Color)
     * @see #setInputColor(Color)
     * @see #setErrorColor(Color)
     */
    public synchronized void selectBlackTextScheme() {
        setOutputColor(Color.black);
        setInputColor(Color.black);
        setErrorColor(Color.black);
    }
    
    /**
     * Sets the color for each 
     * of the three console text streams 
     * as follows:
     *
     * <UL>
     * <LI>Output: <FONT COLOR="black">black</FONT>
     * <LI>Input: <FONT COLOR="blue">blue</FONT>
     * <LI>Error: <FONT COLOR="red">red</FONT>
     * </UL>
     *
     * @see #selectBlackTextScheme()
     * @see #setOutputColor(Color)
     * @see #setInputColor(Color)
     * @see #setErrorColor(Color)
     */
    public synchronized void selectColorTextScheme() {
        setOutputColor(Color.black);
        setInputColor(Color.blue);
        setErrorColor(Color.red);
    }
    
    /**
     * <p>Returns the default monospaced font family name of the font that
     * will be used in the <code>ConsoleTextPane</code> on this system.</p>
     *
     * <p>This method, added in 2.3.3, returns the font family name even if
     * the console is not activated.</p>
     * 
     * <p>Returns the same font family name as the method
     * of the same name in <code>Fonts</code>.</p>
     * 
     * <p>The order of the names tested as of 2.5.0 is:</p>
     * 
     * <ul>
     *   <li>Lucida Console</li>
     *   <li>Lucida Sans Typewriter</li>
     *   <li>Andale Mono</li>
     *   <li>Courier New</li>
     *   <li>Consolas</li>
     *   <li>Monospaced</li>
     *   <li>monospaced</li>
     * </ul>
     * 
     * <p>The first font name that is found is returned.</p>
     */
    public static String getMonospacedFontFamilyName() {
        return Fonts.getMonospacedFontFamilyName();
    }
    
    
    /**
     * <p>Returns the font family name of the console font
     * if the console is activated;
     * otherwise returns "".</p>
     *
     * <p>This method is retained for backward compatibility.</p>
     */
    public final String getFontFamilyName() {
        if (isActivated())
            return window.getFontFamilyName();
        
        return "";
    }
    
    
    /**
     * <p>Returns the actual font size
     * if the console is activated;
     * otherwise returns 0.</p>
     */
    public final int getFontSize() {
        if (isActivated())
            return window.getFontSize();
        
        return 0;
    }
    
    
    /**
     * Get the minimum font size that may be set for the
     * console window.
     */
    public static final int getMinimumFontSize() {
        return ConsoleTextPane.getMinimumFontSize();
    }
    
    
    /**
     * Get the maximum font size that may be set for the
     * console window.
     */
    public static final int getMaximumFontSize() {
        return ConsoleTextPane.getMaximumFontSize();
    }
    
    
    /**
     * <p>Sets the font size for the console to the given size.</p>
     *
     * <p>Point sizes smaller than 10 are set to 10 points.</p>
     *
     * <p>Point sizes larger  than 72 are set to 72 points.</p>
     *
     * <p>Keep in mind that very large font sizes will lead to
     * very few characters per line in the console window.</p> 
     *
     * <p>Does nothing if the console is not activated.</p>
     *
     * @param size the desired font size
     */
    public final void setFontSize(int size) {
        if (isActivated())
            window.setFontSize(size);
    }

    /**
     * Registers the given object 
     * to listen for property change events 
     * generated by this console.
     *
     * @param listener the listener to be registered
     */
    public void addPropertyChangeListener(
        PropertyChangeListener listener) 
    {
        changeAdapter.addPropertyChangeListener(listener);
    }

    /**
     * Registers the given object 
     * to listen for property change events 
     * generated by this console
     * with the provided property name.
     *
     * @param propertyName the name of the desired property 
     * @param listener the listener to be registered
     */
    public void addPropertyChangeListener(
        String propertyName,
        PropertyChangeListener listener) 
    {
        changeAdapter.addPropertyChangeListener(
            propertyName, 
            listener);
    }

    /**
     * Deregisters the given object 
     * from listening for property change events 
     * generated by this console.
     *
     * @param listener the listener to be deregistered
     */
    public void removePropertyChangeListener(
        PropertyChangeListener listener) 
    {
        changeAdapter.removePropertyChangeListener(listener);
    }

    /**
     * Deregisters the given object 
     * from listening for property change events 
     * generated by this console
     * with the provided property name.
     *
     * @param propertyName the name of the desired property 
     * @param listener the listener to be deregistered
     */
    public void removePropertyChangeListener(
        String propertyName,
        PropertyChangeListener listener) 
    {
        changeAdapter.removePropertyChangeListener(
            propertyName, 
            listener);
    }

    ///////////////////////
    // Protected methods //
    ///////////////////////
    
    /**
     * Reads a <CODE>String</CODE> 
     * terminated by a line separator sequence
     * from this console object 
     * and filters it based on the current case action filter.  
     *
     * The line separator sequence is not included 
     * in the returned <CODE>String</CODE>.
     */
    protected synchronized String getOneLine() {
        
        // perform input from an activated console if appropriate
        if (isActivated()) {
            input = null;
            window.setInputMode(true);
            
            // note: wait is released 
            // in the consoleInputPerformed method
            try {
                wait();
            } 
            catch (InterruptedException ex) {}
            finally {
                if (input == null)
                    input = "";
            }
            
            window.setInputMode(false);
        }
            
        // otherwise use the default "in" stream
        else {

            // the following code is adapted from "Core Java"
            // by Horstmann & Cornell

            // initialize necessary variables
            int ch;
            StringBuffer buffer = new StringBuffer("");

            // capture data on input stream 
            // until a newline character is reached
            while (buffer.toString().indexOf(endl) < 0) {
                try {

                    // get a character from the input
                    ch = inStream.read();
                    
                    // end input on strange character
                    if (ch < 0)
                        buffer.append(endl);

                    // otherwise just add character to buffer
                    else buffer.append((char)ch);
                }
                
                // end input if the input stream
                // throws an exception 
                catch (IOException ex) {
                    buffer.append(endl);
                }
            }

            // extract input before line separator
            input = buffer.toString();
            input = input.substring(0, input.indexOf(endl));
        }
        
        // apply current case action filter if applicable
        if (action != null) {
            try {
                XString x = (XString)action.filterStringable(
                    new XString(input));
                input = x.getValue();
            }
            catch (FilterException ex) {}
        }

        return input;
    }
    
    /**
     * Returns the line separator sequence 
     * used by the machine running
     * the Java Virtual Machine.
     */
    protected String getLineSeparator() {
        return endl;
    }

    /**
     * Flushes the given output stream.
     *
     * @param stream the output stream to flush
     * @since   1.0
     */
    protected void flush(int stream) 
        throws IOException
    {
        if (!isActivated())
            outStreams[stream].flush();
    }

    /**
     * Writes the provided text to the given stream.
     * 
     * @param text the text to be written
     * @param stream the output stream to write the data
     */
    protected void write(String text, int stream) {

        // write nothing if text is null
        if (text == null)
            return;
        
        // append to "activated" console if appropriate
        if (isActivated())
            window.consoleOutputPerformed(text, stream);
        
        // otherwise write data to the correct stream
        else {
            try {
                outStreams[stream].write(text.getBytes());
            }
            
            // display error message 
            // if an exception is thrown by the stream
            catch (IOException ex) {
                System.err.print("Could not write to ");
    
                switch (stream) {
                    case ERR:
                        System.err.print("error");
                        break;
                    default:
                        System.err.print("output");
                }
                
                System.err.println(" stream.");
                ex.printStackTrace();
            }

            // flush the stream
            try {
                outStreams[stream].flush();
            } 
            catch (IOException ex) {
                System.err.print("Could not flush ");

                switch (stream) {
                    case ERR:
                        System.err.print("error");
                        break;
                    default:
                        System.err.print("output");
                }
                
                System.err.println(" stream.");
                ex.printStackTrace();
            }
        }
    }
    
    ///////////////////
    // Inner classes //
    ///////////////////
    
    /**
     * <P>Inner class of 
     * <CODE>{@link ConsoleGateway ConsoleGateway}</CODE>
     * that provides input functionality 
     * for a console object.
     *
     * This class provides operations
     * that use the mandatory input mode,
     * or implement the iterative input design pattern.</P>
     *
     * @author  Jeff Raab
     * @author  Richard Rasala
     * @version 2.3.1
     * @since   1.0
     * @see ConsoleGateway
     */
    public class ConsoleInputStream implements Serializable {

        /**
         * Factory used to construct 
         * <CODE>{@link edu.neu.ccs.Stringable Stringable}</CODE> 
         * objects from input stream data.
         */
        protected StringableFactory factory = 
            new StringableFactory(null);

        /**
         * <P>Sets the class of object produced on demand by this
         * input stream to the given <CODE>Stringable</CODE> class.
         * </P>
         *
         * <P>If the given class is not <CODE>Stringable</CODE>,
         * then an exception of type <CODE>Error</CODE> will be
         * thrown.</P>
         * 
         * @param c the desired <CODE>Stringable</CODE> class of
         *          object
         * @see #getDataType()
         */
        public void setDataType(Class c) {
            factory.setDataType(c);
        }
        
        
        /**
         * Returns the <CODE>Stringable</CODE> class of object
         * produced on demand by this input stream.
         *
         * @see #setDataType(Class)
         */
        public Class getDataType() {
            return factory.getDataType();
        }


        /**
         * <P>Returns the <CODE>Stringable</CODE> object obtained
         * from the given <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then a default instance of the
         * current data type will be used to construct the initial
         * object.</P>
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * <P>If the given input filter is not <CODE>null</CODE>,
         * then the object returned may be distinct from the object
         * provided depending on how the filter process operates.</P>
         *
         * <P>This method is the base method that all other
         * <I>demand</I> methods directly or indirectly call.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param data the default data for the object
         * @param obj the object whose state is to be set
         * @param filter the filter to use for the input operation
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable demandObject(
            String prompt, 
            String data,
            Stringable obj,
            StringableFilter filter)
        {
            // if needed create the original object
            if (obj == null)
                obj = factory.getDefaultInstance();
            
            // repeat until the state of the object is successfully set
            while (true) {
            
                // prompt and read the input data
                prompt(prompt, data);
                String inputData = getOneLine();

                // if no input provided use non-null default data 
                if ((inputData.length() == 0) && (data != null))
                    inputData = data;

                // this try deals with parse exception
                try {
                
                    // this try deals with number format exception
                    try {
                    
                        // try to set state of object
                        obj.fromStringData(inputData);

                        // apply the filter for this operation
                        if (filter != null) {
                        
                            // this try deals with filter exception
                            try {
                                obj = filter.filterStringable(obj);
                            }
                            
                            catch (FilterException ex) {
                                // translate filter exception to parse exception
                                throw new ParseException(ex.getMessage(), -1);
                            }
                        }
                    }
                    
                    catch (NumberFormatException ex) {
                        // translate number format exception to parse exception
                        throw new ParseException(ex.getMessage(), -1);
                    }
                                    
                    // if successful return the updated object
                    return obj;
                } 
                
                catch(ParseException e) {
                    // if unsuccessful print error message
                    err.println(XObject.formatErrorMessage(e, inputData));
                }
            }
        }

        /**
         * <P>Returns a <CODE>Stringable</CODE> object created
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public Stringable demandObject(String prompt) {
            return demandObject(prompt, null, null, null);
        }

        /**
         * <P>Returns a <CODE>Stringable</CODE> object created
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable demandObject(
            String prompt, 
            StringableFilter filter) 
        {
            return demandObject(prompt, null, null, filter);
        }
        
        /**
         * <P>Returns a <CODE>Stringable</CODE> object created
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param data the default data for the object
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public Stringable demandObject(
            String prompt, 
            String data) 
        {
            return demandObject(prompt, data, null, null);
        }
        
        /**
         * <P>Returns a <CODE>Stringable</CODE> object created
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param data the default data for the object
         * @param filter the filter to use for the input operation
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public Stringable demandObject(
            String prompt, 
            String data,
            StringableFilter filter) 
        {
            return demandObject(prompt, data, null, filter);
        }
        
        /**
         * <P>Temporarily sets the data type for this stream to the
         * given data type; 
         * creates a <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result;
         * restores the data type for this stream to its original
         * setting;
         * finally returns the object created.</P>
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param dataType the <CODE>Stringable</CODE> data type
         *        of the object
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param data the default data for the object
         * @param filter the filter to use for the input operation
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable demandObject(
            Class dataType,
            String prompt, 
            String data,
            StringableFilter filter) 
        {
            Class oldDataType = getDataType();
            setDataType(dataType);
            
            Stringable obj = demandObject(prompt, data, filter);
            
            setDataType(oldDataType);
            
            return obj;
        }
        
        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  obj the object whose state is to be set
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public void demand(String prompt, Stringable obj) {
            demand(prompt, null, obj, null);
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  obj the object whose state is to be set
         * @param  filter the filter to use for the input operation
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, String, Stringable)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public void demand(
            String prompt, 
            Stringable obj,
            StringableFilter filter) 
        {
            demand(prompt, null, obj, filter);
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  data the default data for the object
         * @param  obj the object whose state is to be set
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable, StringableFilter)
         * @since 2.1
         */
        public void demand(
            String prompt, 
            String data,
            Stringable obj)
        {
            demand(prompt, data, obj, null);
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>If the user provides no input data and
         * the default data is not <CODE>null</CODE>,
         * then the default data is used for input.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  data the default data for the object
         * @param  obj the object whose state is to be set
         * @param  filter the filter to use for the input operation
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #demandObject(String, String, Stringable, StringableFilter)
         * @see #demandObject(String)
         * @see #demandObject(String, StringableFilter)
         * @see #demandObject(String, String)
         * @see #demandObject(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @see #demand(String, Stringable)
         * @see #demand(String, Stringable, StringableFilter)
         * @see #demand(String, String, Stringable)
         * @since 2.1
         */
        public void demand(
            String prompt, 
            String data,
            Stringable obj,
            StringableFilter filter)
        {
            if (obj == null)
                throw new NullPointerException("Null object in demand method.");
            
            demandObject(prompt, data, obj, filter);
        }


        /**
         * <P>Returns the <CODE>Stringable</CODE> object obtained
         * from the given <CODE>Stringable</CODE> object
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then a default instance of the
         * current data type will be used to construct the initial
         * object.</P>
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * <P>If the given input filter is not <CODE>null</CODE>,
         * then the object returned may be distinct from the object
         * provided depending on how the filter process operates.</P>
         *
         * <P>This method is the base method that all other
         * <I>request</I> methods directly or indirectly call.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param obj the object whose state is to be set
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestObject(String)
         * @see #requestObject(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @see #request(String, Stringable)
         * @see #request(String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable requestObject(
            String prompt, 
            Stringable obj,
            StringableFilter filter) throws CancelledException
        {
            // if needed create the original object
            if (obj == null)
                obj = factory.getDefaultInstance();
            
            // repeat until the state of the object is successfully set
            while (true) {
            
                // prompt and read the input data
                prompt(prompt);
                String inputData = getOneLine();

                // if no input provided throw CancelledException
                if (inputData.length() == 0)
                    throw new CancelledException();

                // this try deals with parse exception
                try {
                
                    // this try deals with number format exception
                    try {
                    
                        // try to set state of object
                        obj.fromStringData(inputData);

                        // apply the filter for this operation
                        if (filter != null) {
                        
                            // this try deals with filter exception
                            try {
                                obj = filter.filterStringable(obj);
                            }
                            
                            catch (FilterException ex) {
                                // translate filter exception to parse exception
                                throw new ParseException(ex.getMessage(), -1);
                            }
                        }
                    }
                    
                    catch (NumberFormatException ex) {
                        // translate number format exception to parse exception
                        throw new ParseException(ex.getMessage(), -1);
                    }
                                    
                    // if successful return the updated object
                    return obj;
                } 
                
                catch(ParseException e) {
                    // if unsuccessful print error message
                    err.println(XObject.formatErrorMessage(e, inputData));
                }
            }
        }

        /**
         * <P>Returns the <CODE>Stringable</CODE> object obtained
         * by using the optional input model to acquire the data.</P>
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestObject(String, Stringable, StringableFilter)
         * @see #requestObject(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @see #request(String, Stringable)
         * @see #request(String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable requestObject(
            String prompt) throws CancelledException
        {
            return requestObject(prompt, null, null);
        }

        /**
         * <P>Returns the <CODE>Stringable</CODE> object obtained
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestObject(String, Stringable, StringableFilter)
         * @see #requestObject(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @see #request(String, Stringable)
         * @see #request(String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable requestObject(
            String prompt, 
            StringableFilter filter) throws CancelledException
        {
            return requestObject(prompt, null, filter);
        }

        /**
         * <P>Temporarily sets the data type for this stream to the
         * given data type; 
         * creates a <CODE>Stringable</CODE> object
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result;
         * restores the data type for this stream to its original
         * setting;
         * finally returns the object created.</P>
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestObject(String, Stringable, StringableFilter)
         * @see #requestObject(String)
         * @see #requestObject(String, StringableFilter)
         * @see #request(String, Stringable)
         * @see #request(String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public Stringable requestObject(
            Class dataType,
            String prompt, 
            StringableFilter filter) throws CancelledException
        {
            Class oldDataType = getDataType();
            setDataType(dataType);
            
            Stringable obj = requestObject(prompt, filter);
            
            setDataType(oldDataType);
            
            return obj;
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the optional input model to acquire the data.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  obj the object whose state is to be set
         * @throws CancelledException
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #requestObject(String, Stringable, StringableFilter)
         * @see #requestObject(String)
         * @see #requestObject(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @see #request(String, Stringable, StringableFilter)
         * @since 2.3.1
         */
        public void request(
            String prompt, 
            Stringable obj) throws CancelledException
        {
            requestObject(prompt, obj, null);
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>The optional model is implemented for the console window
         * as follows:</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and a <CODE>CancelledException</CODE>
         * will be thrown.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param  prompt the prompt <CODE>String</CODE> to display
         * @param  obj the object whose state is to be set
         * @param  filter the filter to use for the input operation
         * @throws CancelledException
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @see #requestObject(String, Stringable, StringableFilter)
         * @see #requestObject(String)
         * @see #requestObject(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @see #request(String, Stringable)
         * @since 2.3.1
         */
        public void request(
            String prompt, 
            Stringable obj,
            StringableFilter filter) throws CancelledException
        {
            // throw NullPointerException if the object is null
            if (obj == null)
                throw new NullPointerException("Null object in request method.");
            
            requestObject(prompt, obj, filter);
        }



        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using a variation of the optional input model to acquire the
         * data.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>The variant of the optional model is implemented for the
         * console window as follows:</P>
         *
         * <P>If the user provides valid input data, then the method
         * returns true.</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and the method returns false.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param obj the object whose state is to be set
         * @return <CODE>true</CODE> if the state is set
         *         or <CODE>false</CODE> if no input is provided.
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @since 2.1
         */
        public boolean reading(String prompt, Stringable obj) {
            return reading(prompt, obj, null);
        }

        /**
         * <P>Sets the state of the given <CODE>Stringable</CODE> object
         * by using a variation of the optional input model to acquire the
         * data with the given input filter to constrain the result.</P>
         *
         * <P>If the given <CODE>Stringable</CODE> object
         * is <CODE>null</CODE>, then throws
         * <CODE>NullPointerException</CODE>.
         *
         * <P>The variant of the optional model is implemented for the
         * console window as follows:</P>
         *
         * <P>If the user provides valid input data, then the method
         * returns true.</P>
         *
         * <P>If the user provides no input data, that is, the user
         * presses return on an empty line, then the IO operation is
         * assumed to be cancelled and the method returns false.</P>
         *
         * <P>In particular, with the optional model, it is impossible
         * to input an empty string as the object initialization data.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param obj the object whose state is to be set
         * @param filter the filter to use for the input operation
         * @return <CODE>true</CODE> if the state is set
         *         or <CODE>false</CODE> if no input is provided.
         * @throws NullPointerException if the given object is
         *         <CODE>null</CODE>
         * @since 2.1
         */
        public boolean reading(
            String prompt, 
            Stringable obj,
            StringableFilter filter)
        {
            // throw NullPointerException if the object is null
            if (obj == null)
                throw new NullPointerException("Null object in reading method.");
            
            // repeat until the state of the object is successfully set
            // and then return true
            // or else return false if no input is provided
            while (true) {
        
                // prompt and read data
                prompt(prompt);
                String inputData = getOneLine();
            
                // return false if no data provided
                if (inputData.length() == 0)
                    return false;
                
                // this try deals with parse exception
                try {
                    
                    // this try deals with number format exception
                    try {
                    
                        // try to set state of object
                        obj.fromStringData(inputData);

                        // apply the filter for this operation
                        if (filter != null) {
                         
                            // this try deals with filter exception
                            try {
                                filter.filterStringable(obj);
                            }
                            
                            catch (FilterException ex) {
                                // translate filter exception to parse exception
                                throw new ParseException(ex.getMessage(), -1);
                            }
                        }
                    }
                    
                    catch (NumberFormatException ex) {
                        // translate number format exception to parse exception
                        throw new ParseException(ex.getMessage(), -1);
                    }
                    
                    // if successful return true
                    return true;
                }
                
                catch (ParseException ex) {
                    // if unsuccessful print error message
                    err.println(XObject.formatErrorMessage(ex, inputData));
                }
            }
        }


        /**
         * <P>Demands a <CODE>byte</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandByte(String, StringableFilter)
         * @see #demandByte(String, byte)
         * @see #demandByte(String, byte, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public byte demandByte(String prompt) {
            return demandByte(prompt, null);
        }

        /**
         * <P>Demands a <CODE>byte</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandByte(String)
         * @see #demandByte(String, byte)
         * @see #demandByte(String, byte, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public byte demandByte(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XByte)demandObject
                (XByte.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>byte</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandByte(String)
         * @see #demandByte(String, StringableFilter)
         * @see #demandByte(String, byte, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public byte demandByte(
            String prompt, 
            byte value) 
        {
            return demandByte(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>byte</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandByte(String)
         * @see #demandByte(String, StringableFilter)
         * @see #demandByte(String, byte)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public byte demandByte(
            String prompt, 
            byte value,
            StringableFilter filter) 
        {
            return ((XByte)demandObject
                (XByte.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>byte</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestByte(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public byte requestByte(String prompt) throws CancelledException 
        {
            return requestByte(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>byte</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestByte(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public byte requestByte(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XByte)requestObject
                (XByte.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>short</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandShort(String, StringableFilter)
         * @see #demandShort(String, short)
         * @see #demandShort(String, short, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public short demandShort(String prompt) {
            return demandShort(prompt, null);
        }

        /**
         * <P>Demands a <CODE>short</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandShort(String)
         * @see #demandShort(String, short)
         * @see #demandShort(String, short, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public short demandShort(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XShort)demandObject
                (XShort.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>short</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandShort(String)
         * @see #demandShort(String, StringableFilter)
         * @see #demandShort(String, short, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public short demandShort(
            String prompt, 
            short value) 
        {
            return demandShort(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>short</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandShort(String)
         * @see #demandShort(String, StringableFilter)
         * @see #demandShort(String, short)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public short demandShort(
            String prompt, 
            short value,
            StringableFilter filter) 
        {
            return ((XShort)demandObject
                (XShort.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>short</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestShort(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public short requestShort(String prompt) throws CancelledException 
        {
            return requestShort(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>short</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestShort(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public short requestShort(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XShort)requestObject
                (XShort.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>int</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandInt(String, StringableFilter)
         * @see #demandInt(String, int)
         * @see #demandInt(String, int, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public int demandInt(String prompt) {
            return demandInt(prompt, null);
        }

        /**
         * <P>Demands a <CODE>int</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandInt(String)
         * @see #demandInt(String, int)
         * @see #demandInt(String, int, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public int demandInt(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XInt)demandObject
                (XInt.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>int</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandInt(String)
         * @see #demandInt(String, StringableFilter)
         * @see #demandInt(String, int, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public int demandInt(
            String prompt, 
            int value) 
        {
            return demandInt(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>int</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandInt(String)
         * @see #demandInt(String, StringableFilter)
         * @see #demandInt(String, int)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public int demandInt(
            String prompt, 
            int value,
            StringableFilter filter) 
        {
            return ((XInt)demandObject
                (XInt.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>int</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestInt(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public int requestInt(String prompt) throws CancelledException 
        {
            return requestInt(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>int</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestInt(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public int requestInt(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XInt)requestObject
                (XInt.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>long</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandLong(String, StringableFilter)
         * @see #demandLong(String, long)
         * @see #demandLong(String, long, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public long demandLong(String prompt) {
            return demandLong(prompt, null);
        }

        /**
         * <P>Demands a <CODE>long</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandLong(String)
         * @see #demandLong(String, long)
         * @see #demandLong(String, long, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public long demandLong(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XLong)demandObject
                (XLong.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>long</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandLong(String)
         * @see #demandLong(String, StringableFilter)
         * @see #demandLong(String, long, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public long demandLong(
            String prompt, 
            long value) 
        {
            return demandLong(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>long</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandLong(String)
         * @see #demandLong(String, StringableFilter)
         * @see #demandLong(String, long)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public long demandLong(
            String prompt, 
            long value,
            StringableFilter filter) 
        {
            return ((XLong)demandObject
                (XLong.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>long</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestLong(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public long requestLong(String prompt) throws CancelledException 
        {
            return requestLong(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>long</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestLong(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public long requestLong(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XLong)requestObject
                (XLong.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>float</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandFloat(String, StringableFilter)
         * @see #demandFloat(String, float)
         * @see #demandFloat(String, float, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public float demandFloat(String prompt) {
            return demandFloat(prompt, null);
        }

        /**
         * <P>Demands a <CODE>float</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandFloat(String)
         * @see #demandFloat(String, float)
         * @see #demandFloat(String, float, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public float demandFloat(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XFloat)demandObject
                (XFloat.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>float</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandFloat(String)
         * @see #demandFloat(String, StringableFilter)
         * @see #demandFloat(String, float, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public float demandFloat(
            String prompt, 
            float value) 
        {
            return demandFloat(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>float</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandFloat(String)
         * @see #demandFloat(String, StringableFilter)
         * @see #demandFloat(String, float)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public float demandFloat(
            String prompt, 
            float value,
            StringableFilter filter) 
        {
            return ((XFloat)demandObject
                (XFloat.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>float</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestFloat(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public float requestFloat(String prompt) throws CancelledException 
        {
            return requestFloat(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>float</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestFloat(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public float requestFloat(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XFloat)requestObject
                (XFloat.class, prompt, filter)).getValue();
        }
        
        
         /**
         * <P>Demands a <CODE>double</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandDouble(String, StringableFilter)
         * @see #demandDouble(String, double)
         * @see #demandDouble(String, double, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public double demandDouble(String prompt) {
            return demandDouble(prompt, null);
        }

        /**
         * <P>Demands a <CODE>double</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandDouble(String)
         * @see #demandDouble(String, double)
         * @see #demandDouble(String, double, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public double demandDouble(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XDouble)demandObject
                (XDouble.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>double</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandDouble(String)
         * @see #demandDouble(String, StringableFilter)
         * @see #demandDouble(String, double, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public double demandDouble(
            String prompt, 
            double value) 
        {
            return demandDouble(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>double</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandDouble(String)
         * @see #demandDouble(String, StringableFilter)
         * @see #demandDouble(String, double)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public double demandDouble(
            String prompt, 
            double value,
            StringableFilter filter) 
        {
            return ((XDouble)demandObject
                (XDouble.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>double</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestDouble(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public double requestDouble(String prompt) throws CancelledException 
        {
            return requestDouble(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>double</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestDouble(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public double requestDouble(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XDouble)requestObject
                (XDouble.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>char</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandChar(String, StringableFilter)
         * @see #demandChar(String, char)
         * @see #demandChar(String, char, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public char demandChar(String prompt) {
            return demandChar(prompt, null);
        }

        /**
         * <P>Demands a <CODE>char</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandChar(String)
         * @see #demandChar(String, char)
         * @see #demandChar(String, char, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public char demandChar(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XChar)demandObject
                (XChar.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>char</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandChar(String)
         * @see #demandChar(String, StringableFilter)
         * @see #demandChar(String, char, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public char demandChar(
            String prompt, 
            char value) 
        {
            return demandChar(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>char</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandChar(String)
         * @see #demandChar(String, StringableFilter)
         * @see #demandChar(String, char)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public char demandChar(
            String prompt, 
            char value,
            StringableFilter filter) 
        {
            return ((XChar)demandObject
                (XChar.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>char</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestChar(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public char requestChar(String prompt) throws CancelledException 
        {
            return requestChar(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>char</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestChar(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public char requestChar(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XChar)requestObject
                (XChar.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>boolean</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandBoolean(String, StringableFilter)
         * @see #demandBoolean(String, boolean)
         * @see #demandBoolean(String, boolean, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public boolean demandBoolean(String prompt) {
            return demandBoolean(prompt, null);
        }

        /**
         * <P>Demands a <CODE>boolean</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandBoolean(String)
         * @see #demandBoolean(String, boolean)
         * @see #demandBoolean(String, boolean, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public boolean demandBoolean(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XBoolean)demandObject
                (XBoolean.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>boolean</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandBoolean(String)
         * @see #demandBoolean(String, StringableFilter)
         * @see #demandBoolean(String, boolean, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public boolean demandBoolean(
            String prompt, 
            boolean value) 
        {
            return demandBoolean(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>boolean</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandBoolean(String)
         * @see #demandBoolean(String, StringableFilter)
         * @see #demandBoolean(String, boolean)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public boolean demandBoolean(
            String prompt, 
            boolean value,
            StringableFilter filter) 
        {
            return ((XBoolean)demandObject
                (XBoolean.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>boolean</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestBoolean(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public boolean requestBoolean(String prompt) throws CancelledException 
        {
            return requestBoolean(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>boolean</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestBoolean(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public boolean requestBoolean(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XBoolean)requestObject
                (XBoolean.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>String</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandString(String, StringableFilter)
         * @see #demandString(String, String)
         * @see #demandString(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public String demandString(String prompt) {
            return demandString(prompt, (StringableFilter) null);
        }

        /**
         * <P>Demands a <CODE>String</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandString(String)
         * @see #demandString(String, String)
         * @see #demandString(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public String demandString(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XString)demandObject
                (XString.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>String</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandString(String)
         * @see #demandString(String, StringableFilter)
         * @see #demandString(String, String, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public String demandString(
            String prompt, 
            String value) 
        {
            return demandString(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>String</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandString(String)
         * @see #demandString(String, StringableFilter)
         * @see #demandString(String, String)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public String demandString(
            String prompt, 
            String value,
            StringableFilter filter) 
        {
            return ((XString)demandObject
                (XString.class, prompt, value + "", filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>String</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * <P>With the optional model, it is impossible to
         * input an empty string since this will trigger a
         * <CODE>CancelledException</CODE>.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestString(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public String requestString(String prompt) throws CancelledException 
        {
            return requestString(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>String</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>With the optional model, it is impossible to
         * input an empty string since this will trigger a
         * <CODE>CancelledException</CODE>.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestString(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public String requestString(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XString)requestObject
                (XString.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>BigInteger</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandBigInteger(String, StringableFilter)
         * @see #demandBigInteger(String, BigInteger)
         * @see #demandBigInteger(String, BigInteger, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigInteger demandBigInteger(String prompt) {
            return demandBigInteger(prompt, (StringableFilter) null);
        }

        /**
         * <P>Demands a <CODE>BigInteger</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandBigInteger(String)
         * @see #demandBigInteger(String, BigInteger)
         * @see #demandBigInteger(String, BigInteger, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public BigInteger demandBigInteger(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XBigInteger)demandObject
                (XBigInteger.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>BigInteger</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandBigInteger(String)
         * @see #demandBigInteger(String, StringableFilter)
         * @see #demandBigInteger(String, BigInteger, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigInteger demandBigInteger(
            String prompt, 
            BigInteger value) 
        {
            return demandBigInteger(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>BigInteger</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandBigInteger(String)
         * @see #demandBigInteger(String, StringableFilter)
         * @see #demandBigInteger(String, BigInteger)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigInteger demandBigInteger(
            String prompt, 
            BigInteger value,
            StringableFilter filter) 
        {
            String data = (value == null) ? null : value + "";
            
            return ((XBigInteger)demandObject
                (XBigInteger.class, prompt, data, filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>BigInteger</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestBigInteger(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public BigInteger requestBigInteger(String prompt) throws CancelledException 
        {
            return requestBigInteger(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>BigInteger</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestBigInteger(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public BigInteger requestBigInteger(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XBigInteger)requestObject
                (XBigInteger.class, prompt, filter)).getValue();
        }
        
        
        /**
         * <P>Demands a <CODE>BigDecimal</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandBigDecimal(String, StringableFilter)
         * @see #demandBigDecimal(String, BigDecimal)
         * @see #demandBigDecimal(String, BigDecimal, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigDecimal demandBigDecimal(String prompt) {
            return demandBigDecimal(prompt, (StringableFilter) null);
        }

        /**
         * <P>Demands a <CODE>BigDecimal</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandBigDecimal(String)
         * @see #demandBigDecimal(String, BigDecimal)
         * @see #demandBigDecimal(String, BigDecimal, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public BigDecimal demandBigDecimal(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XBigDecimal)demandObject
                (XBigDecimal.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>BigDecimal</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandBigDecimal(String)
         * @see #demandBigDecimal(String, StringableFilter)
         * @see #demandBigDecimal(String, BigDecimal, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigDecimal demandBigDecimal(
            String prompt, 
            BigDecimal value) 
        {
            return demandBigDecimal(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>BigDecimal</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandBigDecimal(String)
         * @see #demandBigDecimal(String, StringableFilter)
         * @see #demandBigDecimal(String, BigDecimal)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public BigDecimal demandBigDecimal(
            String prompt, 
            BigDecimal value,
            StringableFilter filter) 
        {
            String data = (value == null) ? null : value + "";
            
            return ((XBigDecimal)demandObject
                (XBigDecimal.class, prompt, data, filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>BigDecimal</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestBigDecimal(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public BigDecimal requestBigDecimal(String prompt) throws CancelledException 
        {
            return requestBigDecimal(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>BigDecimal</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestBigDecimal(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public BigDecimal requestBigDecimal(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XBigDecimal)requestObject
                (XBigDecimal.class, prompt, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>Color</CODE> value from the console,
         * by using the mandatory input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @see #demandColor(String, StringableFilter)
         * @see #demandColor(String, Color)
         * @see #demandColor(String, Color, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public Color demandColor(String prompt) {
            return demandColor(prompt, (StringableFilter) null);
        }

        /**
         * <P>Demands a <CODE>Color</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @see #demandColor(String)
         * @see #demandColor(String, Color)
         * @see #demandColor(String, Color, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.3.1
         */
        public Color demandColor(
            String prompt, 
            StringableFilter filter) 
        {
            return ((XColor)demandObject
                (XColor.class, prompt, null, filter)).getValue();
        }
        
        /**
         * <P>Demands a <CODE>Color</CODE> value from the console,
         * by using the mandatory input model to acquire the data
         * with the given default data as a user option.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @see #demandColor(String)
         * @see #demandColor(String, StringableFilter)
         * @see #demandColor(String, Color, StringableFilter)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public Color demandColor(
            String prompt, 
            Color value) 
        {
            return demandColor(prompt, value, null);
        }
    
        /**
         * <P>Demands a <CODE>Color</CODE> value from the console,
         * by using the mandatory input model to acquire the data,
         * with the given default data as a user option,
         * and with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param value the desired default value
         * @param filter the filter to use for the input operation
         * @see #demandColor(String)
         * @see #demandColor(String, StringableFilter)
         * @see #demandColor(String, Color)
         * @see #demandObject(Class, String, String, StringableFilter)
         * @since 2.1
         */
        public Color demandColor(
            String prompt, 
            Color value,
            StringableFilter filter) 
        {
            String data = (value == null)
                ? null
                : XColor.colorToString(value);
            
            return ((XColor)demandObject
                (XColor.class, prompt, data, filter)).getValue();
        }
        
        /**
         * <P>Requests a <CODE>Color</CODE> value from the console,
         * by using the optional input model to acquire the data.</P>
         *
         * @param prompt the prompt <CODE>String</CODE> to display
         * @throws CancelledException
         * @see #requestColor(String, StringableFilter)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public Color requestColor(String prompt) throws CancelledException 
        {
            return requestColor(prompt, null);
        }
        
        /**
         * <P>Requests a <CODE>Color</CODE> value from the console,
         * by using the optional input model to acquire the data
         * with the given input filter to constrain the result.</P>
         *
         * <P>If the given input filter is <CODE>null</CODE>,
         * no input filtering is performed.</P>
         * 
         * @param prompt the prompt <CODE>String</CODE> to display
         * @param filter the filter to use for the input operation
         * @throws CancelledException
         * @see #requestColor(String)
         * @see #requestObject(Class, String, StringableFilter)
         * @since 2.3.1
         */
        public Color requestColor(
            String prompt, 
            StringableFilter filter) throws CancelledException 
        {
            return ((XColor)requestObject
                (XColor.class, prompt, filter)).getValue();
        }
        
    }

    /**
     * <P>Inner class of 
     * <CODE>{@link ConsoleGateway ConsoleGateway}</CODE>, 
     * and derived class of 
     * <CODE>{@link OutputStream OutputStream}</CODE>
     * that provides output functionality 
     * for a console object.
     *
     * @author  Jeff Raab
     * @version 2.1
     * @since   1.0
     * @see ConsoleGateway
     */
    public class ConsoleOutputStream extends OutputStream {
    
        /** Identifier for destination of this output stream. */
        private int stream = OUT;
        
        /**
         * Constructs a console output stream
         * with the given destination.
         *
         * @param destination the destination stream
         */
        public ConsoleOutputStream(int destination) {
            stream = destination;
        }
        
        ////////////////
        // Public API //
        ////////////////
        
        /**
         * Closes this output stream.
         *
         * This implementation does nothing.
         */
        public void close() {}
        
        /**
         * Flushes this output stream.
         */
        public void flush() throws IOException {
            ConsoleGateway.this.flush(stream);
        }
        
        /**
         * Writes <CODE>b.length</CODE> bytes
         * to this output stream.
         *
         * @param b the array of bytes to write
         */
        public void write(byte[] b) {
            ConsoleGateway.this.write(new String(b), stream);
        }

        /**
         * Writes <CODE>length</CODE> bytes 
         * from the given byte array
         * to this output stream,
         * starting at the specified offset.
         *
         * @param b the array of bytes to write
         * @param offset the desired offset
         * @param length the number of bytes to write
         */
        public void write(byte[] b, int offset, int length) {
            ConsoleGateway.this.write(
                new String(b, offset, length), 
                stream);
        }
        
        /**
         * Writes the given byte to this output stream.
         *
         * @param b the byte to write
         */
        public void write(int b) {
            ConsoleGateway.this.write("" + (char)b, stream);
        }
    }
}
