/*
 * @(#)ParserUtilities.java    2.0  30 May 2002
 *
 * Copyright 2004
 * 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.parser;

import edu.neu.ccs.*;
import edu.neu.ccs.util.*;
import java.text.*;
import java.util.Hashtable;
import java.math.*;

/**
 * <P>Provides utility methods for use with parser operations.</P>
 *
 * @author  Jeff Raab
 * @author  Richard Rasala
 * @version 2.2
 * @since 1.0
 * @see Parser
 */
public class ParserUtilities {
    
    /** Default parser used by JPT classes. */
    private static Parser parser = new JPTParser();

    /**
     * Returns the default parser used by JPT classes.
     */
    public static Parser getDefaultParser() {
        return parser;
    }

    /**
     * Sets the default parser used by JPT classes
     * to the given parser.
     *
     * If <CODE>null</CODE>, the default parser is set
     * to the standard default parser for the JPT.
     *
     * @param p the desired default parser
     */
    public static void setDefaultParser(Parser p) {
        if (p == null)
            p = new JPTParser();
            
        parser = p;
    }
    
    /** Return true if x is an <CODE>XNumber</CODE>. */
    public static boolean isXNumber(Object x) {
        return x instanceof XNumber;
    }
    
    /**
     * Return true if x is integral, that is, if
     * x is one of the types:
     * <CODE>XBigInteger</CODE>,
     * <CODE>XLong</CODE>,
     * <CODE>XInt</CODE>,
     * <CODE>XShort</CODE>,
     * <CODE>XByte</CODE>.
     */
    public static boolean isXIntegral(Object x) {
        return
               (x instanceof XBigInteger)
            || (x instanceof XLong)
            || (x instanceof XInt)
            || (x instanceof XShort)
            || (x instanceof XByte);
    }
    
    /**
     * Return true if x is floating, that is, if
     * x is one of the types:
     * <CODE>XBigDecimal</CODE>,
     * <CODE>XDouble</CODE>,
     * <CODE>XFloat</CODE>.
     */
    public static boolean isXFloating(Object x) {
        return
               (x instanceof XBigDecimal)
            || (x instanceof XDouble)
            || (x instanceof XFloat);
    }
    
    /** Return true if x is XBoolean. */
    public static boolean isXBoolean(Object x) {
        return x instanceof XBoolean;
    }
    
    /**
     * Converts the given value to XLong.
     *
     * @param value the value to be converted
     */
    public static XLong toXLong(XNumber value) {
        if (value instanceof XLong)
            return (XLong)value;
        
        return new XLong(value.longValue());
    }
    
    /**
     * Converts the given value to XDouble.
     *
     * @param value the value to be converted
     */
    public static XDouble toXDouble(XNumber value) {
        if (value instanceof XDouble)
            return (XDouble)value;
        
        return new XDouble(value.doubleValue());
    }

    /**
     * Converts the given value to XBigInteger.
     *
     * @param value the value to be converted
     */
    public static XBigInteger toXBigInteger(XNumber value) {
        if (value instanceof XBigInteger)
            return (XBigInteger)value;
        
        if (value instanceof XBigDecimal) {
            XBigDecimal v = (XBigDecimal) value;
            BigDecimal  x = v.getValue();
            return new XBigInteger(x.toBigInteger());
        }
        
        String s = "0";
        
        if (isXIntegral(value)) {
            s = value.longValue() + "";
        }
        else {
            // construct the best integral string s representing value
            double x = value.doubleValue();
            x = Math.rint(x);
            
            DecimalFormat f = new DecimalFormat("#0");
            StringBuffer  b = new StringBuffer(1024);
            FieldPosition p = new FieldPosition(NumberFormat.INTEGER_FIELD);
            
            b = f.format(x, b, p);
            s = b.toString();
        }
        
        return new XBigInteger(new BigInteger(s));
    }

    /**
     * Converts the given value to XBigDecimal.
     *
     * @param value the value to be converted
     */
    public static XBigDecimal toXBigDecimal(XNumber value) {
        if (value instanceof XBigDecimal)
            return (XBigDecimal)value;
        
        if (value instanceof XBigInteger) {
            XBigInteger v = (XBigInteger) value;
            BigInteger  x = v.getValue();
            
            return new XBigDecimal(new BigDecimal(x));
        }
        
        if (isXIntegral(value)) {
            String s = value.longValue() + "";
            
            return new XBigDecimal(new BigDecimal(s));
        }
        
        double z = value.doubleValue();
        
        return new XBigDecimal(new BigDecimal(z));
    }

}
