/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 * @author Morten Jorgensen
 * @author Erwin Bolwidt <ejb@klomp.org>
 * @author John Howard <johnh@schemasoft.com>
 *
 */

package org.apache.xalan.xsltc.runtime;

import java.util.Locale;
import java.util.ResourceBundle;

import java.text.MessageFormat;
import java.text.FieldPosition;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

import org.xml.sax.AttributeList;

import org.apache.xalan.xsltc.*;
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.NodeIterator;
import org.apache.xalan.xsltc.dom.SingletonIterator;

/**
 * Standard XSLT functions. All standard functions expect the current node 
 * and the DOM as their last two arguments.
 */
public final class BasisLibrary implements Operators {

    private final static String EMPTYSTRING = "";

    /**
     * Standard function count(node-set)
     */
    public static int countF(NodeIterator iterator) {
	return(iterator.getLast());
    }

    /**
     * XSLT Standard function sum(node-set). 
     * stringToDouble is inlined
     */
    public static double sumF(NodeIterator iterator, DOM dom) {
	try {
	    double result = 0.0;
	    int node;
	    while ((node = iterator.next()) != NodeIterator.END) {
		result += Double.parseDouble(dom.getNodeValue(node));
	    }
	    return result;
	}
	catch (NumberFormatException e) {
	    return Double.NaN;
	}
    }

    /**
     * XSLT Standard function string()
     */
    public static String stringF(int node, DOM dom) {
	return dom.getNodeValue(node);
    }

    /**
     * XSLT Standard function string(value)
     */
    public static String stringF(Object obj, DOM dom) {
	if (obj instanceof NodeIterator) {
	    return dom.getNodeValue(((NodeIterator)obj).reset().next());
	}
	else if (obj instanceof Node) {
	    return dom.getNodeValue(((Node)obj).node);
	}
	else if (obj instanceof DOM) {
	    return ((DOM)obj).getStringValue();
	}
	else {
	    return obj.toString();
	}
    }

    /**
     * XSLT Standard function string(value)
     */
    public static String stringF(Object obj, int node, DOM dom) {
	if (obj instanceof NodeIterator) {
	    return dom.getNodeValue(((NodeIterator)obj).reset().next());
	}
	else if (obj instanceof Node) {
	    return dom.getNodeValue(((Node)obj).node);
	}
	else if (obj instanceof DOM) {
	    // When the first argument is a DOM we want the whole fecking
	    // DOM and not just a single node - that would not make sense.
	    //return ((DOM)obj).getNodeValue(node);
	    return ((DOM)obj).getStringValue();
	}
	else if (obj instanceof Double) {
	    Double d = (Double)obj;
	    final String result = d.toString();
	    final int length = result.length();
	    if ((result.charAt(length-2)=='.') &&
		(result.charAt(length-1) == '0'))
		return result.substring(0, length-2);
	    else
		return result;
	}
	else {
	    if (obj != null)
		return obj.toString();
	    else
		return stringF(node, dom);
	}
    }

    /**
     * XSLT Standard function number()
     */
    public static double numberF(int node, DOM dom) {
	return stringToReal(dom.getNodeValue(node));
    }

    /**
     * XSLT Standard function number(value)
     */
    public static double numberF(Object obj, DOM dom) {
	if (obj instanceof Double) {
	    return ((Double) obj).doubleValue();
	}
	else if (obj instanceof Integer) {
	    return ((Integer) obj).doubleValue();
	}
	else if (obj instanceof Boolean) {
	    return  ((Boolean) obj).booleanValue() ? 1.0 : 0.0;
	}
	else if (obj instanceof String) {
	    return stringToReal((String) obj);
	}
	else if (obj instanceof NodeIterator) {
	    NodeIterator iter = (NodeIterator) obj;
	    return stringToReal(dom.getNodeValue(iter.reset().next()));
	}
	else if (obj instanceof Node) {
	    return stringToReal(dom.getNodeValue(((Node) obj).node));
	}
	else if (obj instanceof DOM) {
	    return stringToReal(((DOM) obj).getStringValue());
	}
	else {
	    final String className = obj.getClass().getName();
	    runTimeError(INVALID_ARGUMENT_ERR, className, "number()");
	    return 0.0;
	}
    }

    /**
     * XSLT Standard function boolean()
     */
    public static boolean booleanF(Object obj) {
	if (obj instanceof Double) {
	    final double temp = ((Double) obj).doubleValue();
	    return temp != 0.0 && !Double.isNaN(temp);
	}
	else if (obj instanceof Integer) {
	    return ((Integer) obj).doubleValue() != 0;
	}
	else if (obj instanceof Boolean) {
	    return  ((Boolean) obj).booleanValue();
	}
	else if (obj instanceof String) {
	    return !((String) obj).equals(EMPTYSTRING);
	}
	else if (obj instanceof NodeIterator) {
	    NodeIterator iter = (NodeIterator) obj;
	    return iter.reset().next() != NodeIterator.END;
	}
	else if (obj instanceof Node) {
	    return true;
	}
	else if (obj instanceof DOM) {
	    String temp = ((DOM) obj).getStringValue();
	    return !temp.equals(EMPTYSTRING);
	}
	else {
	    final String className = obj.getClass().getName();
	    runTimeError(INVALID_ARGUMENT_ERR, className, "number()");
	}
	return false;
    }

    /**
     * XSLT Standard function substring(). Must take a double because of
     * conversions resulting into NaNs and rounding.
     */
    public static String substringF(String value, double start) {
	try {
	    final int strlen = value.length();
	    int istart = (int)Math.round(start) - 1;

	    if (Double.isNaN(start)) return(EMPTYSTRING);
	    if (istart > strlen) return(EMPTYSTRING);
 	    if (istart < 1) istart = 0;

	    return value.substring(istart);
	}
	catch (IndexOutOfBoundsException e) {
	    runTimeError(RUN_TIME_INTERNAL_ERR, "substring()");
	    return null;
	}
    }

    /**
     * XSLT Standard function substring(). Must take a double because of
     * conversions resulting into NaNs and rounding.
     */
    public static String substringF(String value, double start, double length) {
	try {
	    final int strlen  = value.length();
	    int istart = (int)Math.round(start) - 1;
	    int isum   = istart + (int)Math.round(length);

	    if (Double.isInfinite(length)) isum = Integer.MAX_VALUE;

	    if (Double.isNaN(start) || Double.isNaN(length))
		return(EMPTYSTRING);
	    if (Double.isInfinite(start)) return(EMPTYSTRING);
	    if (istart > strlen) return(EMPTYSTRING);
	    if (isum < 0) return(EMPTYSTRING);
 	    if (istart < 0) istart = 0;

	    if (isum > strlen)
		return value.substring(istart);
	    else
		return value.substring(istart, isum);
	}
	catch (IndexOutOfBoundsException e) {
	    runTimeError(RUN_TIME_INTERNAL_ERR, "substring()");
	    return null;
	}
    }

    /**
     * XSLT Standard function substring-after(). 
     */
    public static String substring_afterF(String value, String substring) {
	final int index = value.indexOf(substring);
	if (index >= 0)
	    return value.substring(index + substring.length());
	else
	    return EMPTYSTRING;
    }

    /**
     * XSLT Standard function substring-before(). 
     */
    public static String substring_beforeF(String value, String substring) {
	final int index = value.indexOf(substring);
	if (index >= 0)
	    return value.substring(0, index);
	else
	    return EMPTYSTRING;
    }

    /**
     * XSLT Standard function translate(). 
     */
    public static String translateF(String value, String from, String to) {
	final int tol = to.length();
	final int froml = from.length();
	final int valuel = value.length();

	final StringBuffer result = new StringBuffer();
	for (int j, i = 0; i < valuel; i++) {
	    final char ch = value.charAt(i);
	    for (j = 0; j < froml; j++) {
		if (ch == from.charAt(j)) {
		    if (j < tol)
			result.append(to.charAt(j));
		    break;
		}
	    }	
	    if (j == froml)
		result.append(ch);
	}
	return result.toString();
    }

    /**
     * XSLT Standard function normalize-space(). 
     */
    public static String normalize_spaceF(int node, DOM dom) {
	return normalize_spaceF(dom.getNodeValue(node));
    }

    /**
     * XSLT Standard function normalize-space(string). 
     */
    public static String normalize_spaceF(String value) {
	int i = 0, n = value.length();
	StringBuffer result = new StringBuffer();

	while (i < n && isWhiteSpace(value.charAt(i)))
	    i++;

	while (true) {
	    while (i < n && !isWhiteSpace(value.charAt(i))) {
		result.append(value.charAt(i++));
	    }
	    if (i == n)
		break;
	    while (i < n && isWhiteSpace(value.charAt(i))) {
		i++;
	    }
	    if (i < n)
		result.append(' ');
	}
	return result.toString();
    }

    /**
     * XSLT Standard function generate-id(). 
     */
    public static String generate_idF(int node) {
	if (node > 0)
	    // Only generate ID if node exists
	    return "N" + node;
	else
	    // Otherwise return an empty string
	    return EMPTYSTRING;
    }
    
    /**
     * utility function for calls to local-name(). 
     */
    public static String getLocalName(String value) {
	int idx = value.lastIndexOf(':');
	if (idx >= 0) value = value.substring(idx + 1);
	idx = value.lastIndexOf('@');
	if (idx >= 0) value = value.substring(idx + 1);
	return(value);
    }

    /**
     * External functions that cannot be resolved are replaced with a call
     * to this method. This method will generate a runtime errors. A good
     * stylesheet checks whether the function exists using conditional
     * constructs, and never really tries to call it if it doesn't exist.
     * But simple stylesheets may result in a call to this method.
     * The compiler should generate a warning if it encounters a call to
     * an unresolved external function.
     */
    public static void unresolved_externalF(String name) {
	runTimeError(EXTERNAL_FUNC_ERR, name);
    }

    /**
     * XSLT Standard function namespace-uri(node-set).
     */
    public static String namespace_uriF(NodeIterator iter, DOM dom) {
	return namespace_uriF(iter.next(), dom);
    }

    /**
     * XSLT Standard function system-property(name)
     */
    public static String system_propertyF(String name) {
	if (name.equals("xsl:version"))
	    return("1.0");
	if (name.equals("xsl:vendor"))
	    return("Apache Software Foundation");
	if (name.equals("xsl:vendor-url"))
	    return("http://xml.apache.org/xalan-j");
	
	runTimeError(INVALID_ARGUMENT_ERR, name, "system-property()");
	return(EMPTYSTRING);
    }

    /**
     * XSLT Standard function namespace-uri(). 
     */
    public static String namespace_uriF(int node, DOM dom) {
	final String value = dom.getNodeName(node);
	final int colon = value.lastIndexOf(':');
	if (colon >= 0)
	    return value.substring(0, colon);
	else
	    return EMPTYSTRING;
    }

    //-- Begin utility functions

    private static boolean isWhiteSpace(char ch) {
	return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
    }

    private static boolean compareStrings(String lstring, String rstring,
					  int op, DOM dom) {
	switch (op) {
	case EQ:
	    return lstring.equals(rstring);

	case NE:
	    return !lstring.equals(rstring);

	case GT:
	    return numberF(lstring, dom) > numberF(rstring, dom);

	case LT:
	    return numberF(lstring, dom) < numberF(rstring, dom);

	case GE:
	    return numberF(lstring, dom) >= numberF(rstring, dom);

	case LE:
	    return numberF(lstring, dom) <= numberF(rstring, dom);

	default:
	    runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
	    return false;
	}
    }

    /**
     * Utility function: node-set/node-set compare. 
     */
    public static boolean compare(NodeIterator left, NodeIterator right,
				  int op, int node, DOM dom) {
	int lnode;
	left.reset();
	
	while ((lnode = left.next()) != NodeIterator.END) {
	    final String lvalue = dom.getNodeValue(lnode);
	    
	    int rnode;
	    right.reset();
	    while ((rnode = right.next()) != NodeIterator.END) {
		if (compareStrings(lvalue, dom.getNodeValue(rnode), op, dom)) {
		    return true;
		}
	    }
	} 
	return false;
    }

    /**
     * Utility function: node/node-set compare.
     */
    public static boolean compare(int node, NodeIterator nodeSet,
				  int op, DOM dom) {
	final String lvalue = dom.getNodeValue(node);
	int rnode;
	//nodeSet.reset();
	while ((rnode = nodeSet.next()) != NodeIterator.END) {
	    if (compareStrings(lvalue, dom.getNodeValue(rnode), op, dom)) {
		return true;
	    }
	} 
	return false;
    }

    public static boolean compare(int node, NodeIterator iterator,
				  int op, int dummy, DOM dom) {
	//iterator.reset();

	int rnode;
	String value;

	switch(op) {
	case EQ:
	    /* TODO:
	     * This needs figuring out: What sort of comparison is done here?
	     * Are we comparing exact node id's, node types, or node values?
	     * Values is the obvious for attributes, but what about elements?
	     */
	    value = dom.getNodeValue(node);
	    while ((rnode = iterator.next()) != NodeIterator.END)
		if (value.equals(dom.getNodeValue(rnode))) return true;
	    // if (rnode == node) return true; It just ain't that easy!!!
	    break;
	case NE:
	    value = dom.getNodeValue(node);
	    while ((rnode = iterator.next()) != NodeIterator.END)
		if (!value.equals(dom.getNodeValue(rnode))) return true;
	    // if (rnode != node) return true;
	    break;
	case LT:
	    // Assume we're comparing document order here
	    while ((rnode = iterator.next()) != NodeIterator.END)
		if (rnode > node) return true;
	    break;
	case GT:
	    // Assume we're comparing document order here
	    while ((rnode = iterator.next()) != NodeIterator.END)
		if (rnode < node) return true;
	    break;
	} 
	return(false);
    }

    public static boolean compare(NodeIterator left, final double rnumber,
				  final int op, final int node, DOM dom) {
	return(compare(left,rnumber,op,dom));
    }

    /**
     * Utility function: node-set/number compare.
     */
    public static boolean compare(NodeIterator left, final double rnumber,
				  final int op, DOM dom) {
	int node;
	//left.reset();

	switch (op) {
	case EQ:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) == rnumber)
		    return true;
	    }
	    break;

	case NE:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) != rnumber)
		    return true;
	    }
	    break;

	case GT:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) > rnumber)
		    return true;
	    }
	    break;

	case LT:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) < rnumber)
		    return true;
	    }
	    break;

	case GE:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) >= rnumber)
		    return true;
	    }
	    break;

	case LE:
	    while ((node = left.next()) != NodeIterator.END) {
		if (numberF(dom.getNodeValue(node), dom) <= rnumber)
		    return true;
	    }
	    break;

	default:
	    runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
	}

	return false;
    }

    /**
     * Utility function: node-set/string comparison. 
     */
    public static boolean compare(NodeIterator left, final String rstring,
				  int op, DOM dom) {
	int node;
	//left.reset();
	while ((node = left.next()) != NodeIterator.END) {
	    if (compareStrings(dom.getNodeValue(node), rstring, op, dom)) {
		return true;
	    }
	}
	return false;
    }

    public static boolean compare(NodeIterator left, final String rstring,
				  int op, int node, DOM dom) {
	
	if (compareStrings(dom.getNodeValue(node), rstring, op, dom)) {
	    return true;
	}
	else {
	    return false;
	}
    }

    public static boolean compare(Object left, Object right,
				  int op, int node, DOM dom) { 
	boolean result = false;
	boolean hasSimpleArgs = hasSimpleType(left) && hasSimpleType(right);

	if (op != EQ && op != NE) {
	    // If node-boolean comparison -> convert node to boolean
	    if (left instanceof Node || right instanceof Node) {
		if (left instanceof Boolean) {
		    right = new Boolean(booleanF(right));
		    hasSimpleArgs = true;
		}
		if (right instanceof Boolean) {
		    left = new Boolean(booleanF(left));
		    hasSimpleArgs = true;
		}
	    }

	    if (hasSimpleArgs) {
		switch (op) {
		case GT:
		    return numberF(left, dom) > numberF(right, dom);
		    
		case LT:
		    return numberF(left, dom) < numberF(right, dom);
		    
		case GE:
		    return numberF(left, dom) >= numberF(right, dom);
		    
		case LE:
		    return numberF(left, dom) <= numberF(right, dom);
		    
		default:
		    runTimeError(RUN_TIME_INTERNAL_ERR, "compare()");
		}
	    }
	    // falls through
	}

	if (hasSimpleArgs) {
	    if (left instanceof Boolean || right instanceof Boolean) {
		result = booleanF(left) == booleanF(right);
	    }
	    else if (left instanceof Double || right instanceof Double ||
		     left instanceof Integer || right instanceof Integer) {
		result = numberF(left, dom) == numberF(right, dom);
	    }
	    else { // compare them as strings
		result = stringF(left, dom).equals(stringF(right, dom));
	    }

	    if (op == Operators.NE) {
		result = !result;
	    }
	}
	else {
	    if (left instanceof Node) {
		left = new SingletonIterator(((Node)left).node);
	    }
	    if (right instanceof Node) {
		right = new SingletonIterator(((Node)right).node);
	    }

	    if (hasSimpleType(left) ||
		left instanceof DOM && right instanceof NodeIterator) {
		// swap operands
		final Object temp = right; right = left; left = temp;
	    }

	    if (left instanceof DOM) {
		if (right instanceof Boolean) {
		    result = ((Boolean)right).booleanValue();
		    return result == (op == Operators.EQ);
		}

		final String sleft = ((DOM)left).getStringValue();

		if (right instanceof Number) {
		    result = ((Number)right).doubleValue() ==
			stringToReal(sleft);
		}
		else if (right instanceof String) {
		    result = sleft.equals((String)right);
		}
		else if (right instanceof DOM) {
		    result = sleft.equals(((DOM)right).getStringValue());
		}

		if (op == Operators.NE) {
		    result = !result;
		}
		return result;
	    }

	    // Next, node-set/t for t in {real, string, node-set, result-tree}

	    NodeIterator iter = ((NodeIterator)left).reset();

	    if (right instanceof NodeIterator) {
		result = compare(iter, (NodeIterator)right, op, node, dom);
	    }
	    else if (right instanceof String) {
		//result = compare(iter, (String)right, op, node, dom);
		result = compare(iter, (String)right, op, dom);
	    }	
	    else if (right instanceof Number) {
		final double temp = ((Number)right).doubleValue();
		result = compare(iter, temp, op, dom);
	    }
	    else if (right instanceof Boolean) {
		boolean temp = ((Boolean)right).booleanValue();
		result = (iter.reset().next() != NodeIterator.END) == temp;
	    }
	    else if (right instanceof DOM) {
		result = compare(iter, ((DOM)right).getStringValue(),
				 op, node, dom);
	    }
	    else if (right == null) {
		return(false);
	    }
	    else {
		final String className = right.getClass().getName();
		runTimeError(INVALID_ARGUMENT_ERR, className, "compare()");
	    }
	}
	return result;
    }

    /**
     * Utility function: used to test context node's language
     */
    public static boolean testLanguage(String testLang, DOM dom, int node) {
	// language for context node (if any)
	String nodeLang = dom.getLanguage(node);
	if (nodeLang == null)
	    return(false);
	else
	    nodeLang = nodeLang.toLowerCase();

	// compare context node's language agains test language
	testLang = testLang.toLowerCase();
	if (testLang.length() == 2) {
	    return(nodeLang.startsWith(testLang));
	}
	else {
	    return(nodeLang.equals(testLang));
	}
    }

    private static boolean hasSimpleType(Object obj) {
	return obj instanceof Boolean || obj instanceof Double ||
	    obj instanceof Integer || obj instanceof String ||
	    obj instanceof Node;
    }

    /**
     * Utility function: used in StringType to convert a string to a real.
     */
    public static double stringToReal(String s) {
	try {
	    return Double.valueOf(s).doubleValue();
	}
	catch (NumberFormatException e) {
	    return Double.NaN;
	}
    }

    /**
     * Utility function: used in StringType to convert a string to an int.
     */
    public static int stringToInt(String s) {
	try {
	    return Integer.parseInt(s);
	}
	catch (NumberFormatException e) {
	    return(-1); // ???
	}
    }

    private static double lowerBounds = 0.001;
    private static double upperBounds = 10000000;
    private static DecimalFormat defaultFormatter;
    private static String defaultPattern = "";

    static {
	defaultFormatter = new DecimalFormat();
	defaultFormatter.setGroupingUsed(false);
    }

    /**
     * Utility function: used in RealType to convert a real to a string.
     * Removes the decimal if null.
     */
    public static String realToString(double d) {
	final double m = Math.abs(d);
	if ((m >= lowerBounds) && (m < upperBounds)) {
	    final String result = Double.toString(d);
	    final int length = result.length();
	    // Remove leading zeros.
	    if ((result.charAt(length-2) == '.') &&
		(result.charAt(length-1) == '0'))
		return result.substring(0, length-2);
	    else
		return result;
	}
	else {
	    if (Double.isNaN(d) || Double.isInfinite(d))
		return(Double.toString(d));
	    return formatNumber(d, defaultPattern, defaultFormatter);
	}
    }

    /**
     * Utility function: used in RealType to convert a real to an integer
     */
    public static int realToInt(double d) {
	return (int)d;
    }

    /**
     * Utility function: used to format/adjust  a double to a string. The 
     * DecimalFormat object comes from the 'format_symbols' hashtable in 
     * AbstractTranslet.
     */
    private static FieldPosition _fieldPosition = new FieldPosition(0);

    public static String formatNumber(double number, String pattern,
				      DecimalFormat formatter) {
	try {
	    StringBuffer result = new StringBuffer();
	    formatter.applyLocalizedPattern(pattern);
	    formatter.format(number, result, _fieldPosition);
	    return(result.toString());
	}
	catch (IllegalArgumentException e) {
	    runTimeError(FORMAT_NUMBER_ERR, Double.toString(number), pattern);
	    return(EMPTYSTRING);
	}
    }
    
    /**
     * Utility function: used to convert references to node-sets. If the
     * obj is an instanceof Node then create a singleton iterator.
     */
    public static NodeIterator referenceToNodeSet(Object obj) {
	try {
	    // Convert var/param -> node
	    if (obj instanceof Node) {
		return(new SingletonIterator(((Node)obj).node));
	    }
	    // Convert var/param -> node-set
	    else if (obj instanceof NodeIterator) {
		return(((NodeIterator)obj).cloneIterator());
	    }
	    // Convert var/param -> result-tree fragment
	    else if (obj instanceof DOM) {
		DOM dom = (DOM)obj;
		return(dom.getIterator());
	    }
	    else {
		final String className = obj.getClass().getName();
		runTimeError(DATA_CONVERSION_ERR, "reference", className);
		return null;
	    }
	}
	catch (ClassCastException e) {
	    runTimeError(DATA_CONVERSION_ERR, "reference", "node-set");
	    return null;
	}
    }

    /**
     * Utility function: used with nth position filters to convert a sequence
     * of nodes to just one single node (the one at position n).
     */
    public static NodeIterator getSingleNode(NodeIterator iterator) {
	int node = iterator.next();
	return(new SingletonIterator(node));
    }

    /**
     * Utility function: used in xsl:copy.
     */
    private static char[] _characterArray = new char[32];

    public static void copy(Object obj,
			    TransletOutputHandler handler,
			    int node,
			    DOM dom) {
	try {
	    if (obj instanceof NodeIterator) {
		NodeIterator iter = (NodeIterator) obj;
		dom.copy(iter.reset(), handler);
	    }
	    else if (obj instanceof Node) {
		dom.copy(((Node) obj).node, handler);
	    }
	    else if (obj instanceof DOM) {
		((DOM)obj).copy(1, handler);
	    }
	    else {
		String string = obj.toString();		// or call stringF()
		final int length = string.length();
		if (length > _characterArray.length)
		    _characterArray = new char[length];
		string.getChars(0, length, _characterArray, 0);
		handler.characters(_characterArray, 0, length);
	    }
	}
	catch (TransletException e) {
	    runTimeError(RUN_TIME_COPY_ERR);
	}
    }
    
    public static final int RUN_TIME_INTERNAL_ERR   = 0;
    public static final int RUN_TIME_COPY_ERR       = 1;
    public static final int DATA_CONVERSION_ERR     = 2;
    public static final int EXTERNAL_FUNC_ERR       = 3;
    public static final int EQUALITY_EXPR_ERR       = 4;
    public static final int INVALID_ARGUMENT_ERR    = 5;
    public static final int FORMAT_NUMBER_ERR       = 6;
    public static final int ITERATOR_CLONE_ERR      = 7;
    public static final int AXIS_SUPPORT_ERR        = 8;
    public static final int TYPED_AXIS_SUPPORT_ERR  = 9;
    public static final int STRAY_ATTRIBUTE_ERR     = 10; 
    public static final int STRAY_NAMESPACE_ERR     = 11;
    public static final int NAMESPACE_PREFIX_ERR    = 12;
    public static final int DOM_ADAPTER_INIT_ERR    = 13;

    // All error messages are localized and are stored in resource bundles.
    // This array and the following 4 strings are read from that bundle.
    private static String[] _errorMessages;
    
    public final static String ERROR_MESSAGES_KEY = "error-messages";

    static {
	String resource = "org.apache.xalan.xsltc.runtime.ErrorMessages";
	ResourceBundle bundle = ResourceBundle.getBundle(resource);
	_errorMessages  = bundle.getStringArray(ERROR_MESSAGES_KEY);
    }

    /**
     * Print a run-time error message.
     */
    public static void runTimeError(int code) {
	throw new RuntimeException(_errorMessages[code]);
    }

    public static void runTimeError(int code, Object[] args) {
	final String message = MessageFormat.format(_errorMessages[code],args);
	throw new RuntimeException(message);
    }

    public static void runTimeError(int code, Object arg0) {
	runTimeError(code, new Object[]{ arg0 } );
    }

    public static void runTimeError(int code, Object arg0, Object arg1) {
	runTimeError(code, new Object[]{ arg0, arg1 } );
    }

    public static void consoleOutput(String msg) {
	System.out.println(msg);
    }

    //-- End utility functions
}
