/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id$
 */

package org.apache.xalan.xsltc.runtime;

import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.xml.transform.dom.DOMSource;

import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.dom.AbsoluteIterator;
import org.apache.xml.dtm.Axis;
import org.apache.xalan.xsltc.dom.DOMAdapter;
import org.apache.xalan.xsltc.dom.MultiDOM;
import org.apache.xalan.xsltc.dom.SingletonIterator;
import org.apache.xalan.xsltc.dom.StepIterator;
import org.apache.xml.dtm.DTMAxisIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMDefaultBase;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.apache.xml.serializer.NamespaceMappings;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.utils.XML11Char;

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

    private final static String EMPTYSTRING = "";

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

    /**
     * Standard function position()
     * @deprecated This method exists only for backwards compatibility with old
     *             translets.  New code should not reference it.
     */
    public static int positionF(DTMAxisIterator iterator) {
        return iterator.isReverse()
                     ? iterator.getLast() - iterator.getPosition() + 1
                     : iterator.getPosition();
    }

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

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

    /**
     * XSLT Standard function string(value)
     */
    public static String stringF(Object obj, DOM dom) {
	if (obj instanceof DTMAxisIterator) {
	    return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
	}
	else if (obj instanceof Node) {
	    return dom.getStringValueX(((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 DTMAxisIterator) {
	    return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
	}
	else if (obj instanceof Node) {
	    return dom.getStringValueX(((Node)obj).node);
	}
	else if (obj instanceof DOM) {
	    // When the first argument is a DOM we want the whole
	    // DOM and not just a single node - that would not make sense.
	    //return ((DOM)obj).getStringValueX(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.getStringValueX(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 DTMAxisIterator) {
	    DTMAxisIterator iter = (DTMAxisIterator) obj;
	    return stringToReal(dom.getStringValueX(iter.reset().next()));
	}
	else if (obj instanceof Node) {
	    return stringToReal(dom.getStringValueX(((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 round()
     */
    public static double roundF(double d) {
            return (d<-0.5 || d>0.0)?Math.floor(d+0.5):((d==0.0)?
                        d:(Double.isNaN(d)?Double.NaN:-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 DTMAxisIterator) {
	    DTMAxisIterator iter = (DTMAxisIterator) obj;
	    return iter.reset().next() != DTMAxisIterator.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, "boolean()");
	}
	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.getStringValueX(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);
    }

    /**
     * Utility function to throw a runtime error on the use of an extension 
     * function when the secure processing feature is set to true.
     */
    public static void unallowed_extension_functionF(String name) {
        runTimeError(UNALLOWED_EXTENSION_FUNCTION_ERR, name);
    }

    /**
     * Utility function to throw a runtime error on the use of an extension 
     * element when the secure processing feature is set to true.
     */
    public static void unallowed_extension_elementF(String name) {
        runTimeError(UNALLOWED_EXTENSION_ELEMENT_ERR, name);
    }

    /**
     * Utility function to throw a runtime error for an unsupported element.
     * 
     * This is only used in forward-compatibility mode, when the control flow
     * cannot be determined. In 1.0 mode, the error message is emitted at 
     * compile time.
     */
    public static void unsupported_ElementF(String qname, boolean isExtension) {
	if (isExtension)
	    runTimeError(UNSUPPORTED_EXT_ERR, qname);
	else
	    runTimeError(UNSUPPORTED_XSL_ERR, qname);
    }     

    /**
     * XSLT Standard function namespace-uri(node-set).
     */
    public static String namespace_uriF(DTMAxisIterator 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 (Xalan XSLTC)");
	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;
    }

    /**
     * Implements the object-type() extension function.
     * 
     * @see <a href="http://www.exslt.org/">EXSLT</a>
     */
    public static String objectTypeF(Object obj)
    {
      if (obj instanceof String)
        return "string";
      else if (obj instanceof Boolean)
        return "boolean";
      else if (obj instanceof Number)
        return "number";
      else if (obj instanceof DOM)
        return "RTF";
      else if (obj instanceof DTMAxisIterator)
        return "node-set";
      else
        return "unknown";
    }  

    /**
     * Implements the nodeset() extension function. 
     */
    public static DTMAxisIterator nodesetF(Object obj) {
	if (obj instanceof DOM) {
	   //final DOMAdapter adapter = (DOMAdapter) obj;
	   final DOM dom = (DOM)obj;
	   return new SingletonIterator(dom.getDocument(), true);
	}
        else if (obj instanceof DTMAxisIterator) {
	   return (DTMAxisIterator) obj;
        }
        else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, "node-set", className);
	    return null;
        }
    }

    //-- 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 Operators.EQ:
	    return lstring.equals(rstring);

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

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

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

    case Operators.GE:
	    return numberF(lstring, dom) >= numberF(rstring, dom);
        
    case Operators.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(DTMAxisIterator left, DTMAxisIterator right,
				  int op, DOM dom) {
	int lnode;
	left.reset();
	
	while ((lnode = left.next()) != DTMAxisIterator.END) {
	    final String lvalue = dom.getStringValueX(lnode);
	    
	    int rnode;
	    right.reset();
	    while ((rnode = right.next()) != DTMAxisIterator.END) {
                // String value must be the same if both nodes are the same
                if (lnode == rnode) {
                    if (op == Operators.EQ) {
                        return true;
                    } else if (op == Operators.NE) {
                        continue;
                    }
                }
		if (compareStrings(lvalue, dom.getStringValueX(rnode), op,
                                   dom)) {
		    return true;
		}
	    }
	} 
	return false;
    }

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

	int rnode;
	String value;

	switch(op) {
    case Operators.EQ:
            rnode = iterator.next();
            if (rnode != DTMAxisIterator.END) {
	        value = dom.getStringValueX(node);
                do {
		    if (node == rnode
                          || value.equals(dom.getStringValueX(rnode))) {
                       return true;
                    }
	        } while ((rnode = iterator.next()) != DTMAxisIterator.END);
            }
	    break;
    case Operators.NE:
            rnode = iterator.next();
            if (rnode != DTMAxisIterator.END) {
	        value = dom.getStringValueX(node);
                do {
		    if (node != rnode
                          && !value.equals(dom.getStringValueX(rnode))) {
                        return true;
                    }
	        } while ((rnode = iterator.next()) != DTMAxisIterator.END);
            }
	    break;
    case Operators.LT:
	    // Assume we're comparing document order here
	    while ((rnode = iterator.next()) != DTMAxisIterator.END) {
		if (rnode > node) return true;
	    }
	    break;
    case Operators.GT:
	    // Assume we're comparing document order here
	    while ((rnode = iterator.next()) != DTMAxisIterator.END) {
		if (rnode < node) return true;
	    }
	    break;
	} 
	return(false);
    }

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

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

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

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

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

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

    case Operators.LE:
	    while ((node = left.next()) != DTMAxisIterator.END) {
		if (numberF(dom.getStringValueX(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(DTMAxisIterator left, final String rstring,
				  int op, DOM dom) {
	int node;
	//left.reset();
	while ((node = left.next()) != DTMAxisIterator.END) {
	    if (compareStrings(dom.getStringValueX(node), rstring, op, dom)) {
		return true;
	    }
	}
	return false;
    }


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

    if (op != Operators.EQ && op != Operators.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 Operators.GT:
		    return numberF(left, dom) > numberF(right, dom);
		    
        case Operators.LT:
		    return numberF(left, dom) < numberF(right, dom);
		    
        case Operators.GE:
		    return numberF(left, dom) >= numberF(right, dom);
		    
        case Operators.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 DTMAxisIterator) {
		// swap operands and operator
		final Object temp = right; right = left; left = temp;
                op = Operators.swapOp(op);
	    }

	    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}

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

	    if (right instanceof DTMAxisIterator) {
		result = compare(iter, (DTMAxisIterator)right, op, dom);
	    }
	    else if (right instanceof String) {
		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() != DTMAxisIterator.END) == temp;
	    }
	    else if (right instanceof DOM) {
		result = compare(iter, ((DOM)right).getStringValue(),
				 op, 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 || obj instanceof DOM; 
    }

    /**
     * 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 final int DOUBLE_FRACTION_DIGITS = 340;
    private static final double lowerBounds = 0.001;
    private static final double upperBounds = 10000000;
    private static DecimalFormat defaultFormatter;
    private static String defaultPattern = "";

    static {
	NumberFormat f = NumberFormat.getInstance(Locale.getDefault());
	defaultFormatter = (f instanceof DecimalFormat) ?
	    (DecimalFormat) f : new DecimalFormat();
	// Set max fraction digits so that truncation does not occur. Setting 
        // the max to Integer.MAX_VALUE may cause problems with some JDK's.
	defaultFormatter.setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
        defaultFormatter.setMinimumFractionDigits(0);
        defaultFormatter.setMinimumIntegerDigits(1);
        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 'formatSymbols' hashtable in 
     * AbstractTranslet.
     */
    private static FieldPosition _fieldPosition = new FieldPosition(0);

    public static String formatNumber(double number, String pattern,
				      DecimalFormat formatter) {
        // bugzilla fix 12813 
	if (formatter == null) {
	    formatter = defaultFormatter;
	}
	try {
	    StringBuffer result = new StringBuffer();
	    if (pattern != defaultPattern) {
		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 DTMAxisIterator referenceToNodeSet(Object obj) {
	// Convert var/param -> node
	if (obj instanceof Node) {
	    return(new SingletonIterator(((Node)obj).node));
	}
	// Convert var/param -> node-set
	else if (obj instanceof DTMAxisIterator) {
        return(((DTMAxisIterator)obj).cloneIterator().reset());
	}
	else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, "node-set");
	    return null;
	}
    }
    
    /**
     * Utility function: used to convert reference to org.w3c.dom.NodeList.
     */
    public static NodeList referenceToNodeList(Object obj, DOM dom) {
        if (obj instanceof Node || obj instanceof DTMAxisIterator) {
            DTMAxisIterator iter = referenceToNodeSet(obj);
            return dom.makeNodeList(iter);
        }
        else if (obj instanceof DOM) {
          dom = (DOM)obj;
          return dom.makeNodeList(DTMDefaultBase.ROOTNODE);
        }
	else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, 
                "org.w3c.dom.NodeList");
	    return null;
	}
    }

    /**
     * Utility function: used to convert reference to org.w3c.dom.Node.
     */
    public static org.w3c.dom.Node referenceToNode(Object obj, DOM dom) {
        if (obj instanceof Node || obj instanceof DTMAxisIterator) {
            DTMAxisIterator iter = referenceToNodeSet(obj);
            return dom.makeNode(iter);
        }
        else if (obj instanceof DOM) {
          dom = (DOM)obj;
          DTMAxisIterator iter = dom.getChildren(DTMDefaultBase.ROOTNODE);
          return dom.makeNode(iter);
        }
	else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, "org.w3c.dom.Node");
	    return null;
	}
    }
   
    /**
     * Utility function: used to convert reference to long.
     */
    public static long referenceToLong(Object obj) {
        if (obj instanceof Number) {
            return ((Number) obj).longValue();    // handles Integer and Double
        }
        else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, Long.TYPE);
	    return 0;
        }
    }
            
    /**
     * Utility function: used to convert reference to double.
     */
    public static double referenceToDouble(Object obj) {
        if (obj instanceof Number) {
            return ((Number) obj).doubleValue();   // handles Integer and Double
        }
        else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, Double.TYPE);
	    return 0;
        }
    }

    /**
     * Utility function: used to convert reference to boolean.
     */
    public static boolean referenceToBoolean(Object obj) {
        if (obj instanceof Boolean) {
            return ((Boolean) obj).booleanValue();
        }
        else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, Boolean.TYPE);
	    return false;
        }
    }

    /**
     * Utility function: used to convert reference to String.
     */
    public static String referenceToString(Object obj, DOM dom) {
        if (obj instanceof String) {
            return (String) obj;
        }
        else if (obj instanceof DTMAxisIterator) {
	    return dom.getStringValueX(((DTMAxisIterator)obj).reset().next());
	}
	else if (obj instanceof Node) {
	    return dom.getStringValueX(((Node)obj).node);
	}
	else if (obj instanceof DOM) {
	    return ((DOM) obj).getStringValue();
	}
        else {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, className, String.class);
	    return null;
        }
    }

    /**
     * Utility function used to convert a w3c Node into an internal DOM iterator. 
     */
    public static DTMAxisIterator node2Iterator(org.w3c.dom.Node node,
	Translet translet, DOM dom) 
    {
        final org.w3c.dom.Node inNode = node;
        // Create a dummy NodeList which only contains the given node to make 
        // use of the nodeList2Iterator() interface.
        org.w3c.dom.NodeList nodelist = new org.w3c.dom.NodeList() {            
            public int getLength() {
                return 1;
            }
            
            public org.w3c.dom.Node item(int index) {
                if (index == 0)
                    return inNode;
                else
                    return null;
            }
        };
        
        return nodeList2Iterator(nodelist, translet, dom);
    }
    
    /**
     * Utility function used to copy a node list to be under a parent node.
     */
    private static void copyNodes(org.w3c.dom.NodeList nodeList, 
	org.w3c.dom.Document doc, org.w3c.dom.Node parent)
    {
        final int size = nodeList.getLength();

          // copy Nodes from NodeList into new w3c DOM
        for (int i = 0; i < size; i++) 
        {
            org.w3c.dom.Node curr = nodeList.item(i);
            int nodeType = curr.getNodeType();
            String value = null;
            try {
                value = curr.getNodeValue();
            } catch (DOMException ex) {
                runTimeError(RUN_TIME_INTERNAL_ERR, ex.getMessage());
                return;
            }
            
            String nodeName = curr.getNodeName();
            org.w3c.dom.Node newNode = null; 
            switch (nodeType){
                case org.w3c.dom.Node.ATTRIBUTE_NODE:
                     newNode = doc.createAttributeNS(curr.getNamespaceURI(), 
			nodeName);
                     break;
                case org.w3c.dom.Node.CDATA_SECTION_NODE: 
                     newNode = doc.createCDATASection(value);
                     break;
                case org.w3c.dom.Node.COMMENT_NODE: 
                     newNode = doc.createComment(value);
                     break;
                case org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE: 
                     newNode = doc.createDocumentFragment();
                     break;
                case org.w3c.dom.Node.DOCUMENT_NODE:
                     newNode = doc.createElementNS(null, "__document__");
                     copyNodes(curr.getChildNodes(), doc, newNode);
                     break;
                case org.w3c.dom.Node.DOCUMENT_TYPE_NODE:
                     // nothing?
                     break;
                case org.w3c.dom.Node.ELEMENT_NODE: 
                     // For Element node, also copy the children and the 
		     // attributes.
                     org.w3c.dom.Element element = doc.createElementNS(
			curr.getNamespaceURI(), nodeName);
                     if (curr.hasAttributes())
                     {
                       org.w3c.dom.NamedNodeMap attributes = curr.getAttributes();
                       for (int k = 0; k < attributes.getLength(); k++) {
                         org.w3c.dom.Node attr = attributes.item(k);
                         element.setAttributeNS(attr.getNamespaceURI(), 
                                 attr.getNodeName(), attr.getNodeValue());
                       }
                     }
                     copyNodes(curr.getChildNodes(), doc, element);
                     newNode = element;
                     break;
                case org.w3c.dom.Node.ENTITY_NODE: 
                     // nothing ? 
                     break;
                case org.w3c.dom.Node.ENTITY_REFERENCE_NODE: 
                     newNode = doc.createEntityReference(nodeName);
                     break;
                case org.w3c.dom.Node.NOTATION_NODE: 
                     // nothing ? 
                     break;
                case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: 
                     newNode = doc.createProcessingInstruction(nodeName,
                        value);
                     break;
                case org.w3c.dom.Node.TEXT_NODE: 
                     newNode = doc.createTextNode(value);
                     break;
            }
            try {
                parent.appendChild(newNode);
            } catch (DOMException e) {
                runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
                return;
            }           
        }
    }

    /**
     * Utility function used to convert a w3c NodeList into a internal
     * DOM iterator. 
     */
    public static DTMAxisIterator nodeList2Iterator(
                                        org.w3c.dom.NodeList nodeList,
                                    	Translet translet, DOM dom) 
    {
	// w3c NodeList -> w3c DOM
	Document doc = null;
	try {
	    doc = ((AbstractTranslet) translet).newDocument("", "__top__");
	} 
        catch (javax.xml.parsers.ParserConfigurationException e) {
	    runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
            return null;
	}
        
        // Copy all the nodes in the nodelist to be under the top element
        copyNodes(nodeList, doc, doc.getDocumentElement());

        // w3cDOM -> DTM -> DOMImpl
	if (dom instanceof MultiDOM) {
            final MultiDOM multiDOM = (MultiDOM) dom;

	    DTMDefaultBase dtm = (DTMDefaultBase)((DOMAdapter)multiDOM.getMain()).getDOMImpl();
	    DTMManager dtmManager = dtm.getManager();
	    
	    DOM idom = (DOM)dtmManager.getDTM(new DOMSource(doc), false,
					      null, true, false);
	    // Create DOMAdapter and register with MultiDOM
	    DOMAdapter domAdapter = new DOMAdapter(idom, 
                translet.getNamesArray(),
                translet.getUrisArray(),
                translet.getTypesArray(),
		translet.getNamespaceArray());
            multiDOM.addDOMAdapter(domAdapter);

	    DTMAxisIterator iter1 = idom.getAxisIterator(Axis.CHILD);
	    DTMAxisIterator iter2 = idom.getAxisIterator(Axis.CHILD);
            DTMAxisIterator iter = new AbsoluteIterator(
                new StepIterator(iter1, iter2));

 	    iter.setStartNode(DTMDefaultBase.ROOTNODE);
	    return iter;
	}
        else {
	    runTimeError(RUN_TIME_INTERNAL_ERR, "nodeList2Iterator()");
	    return null;
        }
    }

    /**
     * Utility function used to convert references to DOMs. 
     */
    public static DOM referenceToResultTree(Object obj) {
	try {
	    return ((DOM) obj);
	}
	catch (IllegalArgumentException e) {
	    final String className = obj.getClass().getName();
	    runTimeError(DATA_CONVERSION_ERR, "reference", className);
	    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 DTMAxisIterator getSingleNode(DTMAxisIterator 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,
 			    SerializationHandler handler,
			    int node,
			    DOM dom) {
	try {
	    if (obj instanceof DTMAxisIterator) 
      {
		DTMAxisIterator iter = (DTMAxisIterator) 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(((org.apache.xml.dtm.ref.DTMDefaultBase)((DOMAdapter)obj).getDOMImpl()).getDocument(), handler);
		DOM newDom = (DOM)obj;
		newDom.copy(newDom.getDocument(), 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 (SAXException e) {
	    runTimeError(RUN_TIME_COPY_ERR);
	}
    }
    
    /**
     * Utility function to check if xsl:attribute has a valid qname
     * This method should only be invoked if the name attribute is an AVT
     */    
    public static void checkAttribQName(String name) {
        final int firstOccur = name.indexOf(":");
        final int lastOccur = name.lastIndexOf(":");
        final String localName = name.substring(lastOccur + 1);
        
        if (firstOccur > 0) {
            final String newPrefix = name.substring(0, firstOccur); 
        
            if (firstOccur != lastOccur) {
               final String oriPrefix = name.substring(firstOccur+1, lastOccur); 
                if (!XML11Char.isXML11ValidNCName(oriPrefix)) {
                    // even though the orignal prefix is ignored, it should still get checked for valid NCName
                    runTimeError(INVALID_QNAME_ERR,oriPrefix+":"+localName);
                }
            }
            
            // prefix must be a valid NCName
            if (!XML11Char.isXML11ValidNCName(newPrefix)) {
                runTimeError(INVALID_QNAME_ERR,newPrefix+":"+localName); 
            }  
        }
                
        // local name must be a valid NCName and must not be XMLNS
        if ((!XML11Char.isXML11ValidNCName(localName))||(localName.equals(Constants.XMLNS_PREFIX))) {
            runTimeError(INVALID_QNAME_ERR,localName); 
        }
    }
    
    /**
     * Utility function to check if a name is a valid ncname
     * This method should only be invoked if the attribute value is an AVT
     */    
    public static void checkNCName(String name) {
        if (!XML11Char.isXML11ValidNCName(name)) {
            runTimeError(INVALID_NCNAME_ERR,name); 
        }  
    }        

    /**
     * Utility function to check if a name is a valid qname
     * This method should only be invoked if the attribute value is an AVT
     */    
    public static void checkQName(String name) {
        if (!XML11Char.isXML11ValidQName(name)) {
            runTimeError(INVALID_QNAME_ERR,name); 
        }  
    }
    
    /**
     * Utility function for the implementation of xsl:element.
     */
    public static String startXslElement(String qname, String namespace,
	SerializationHandler handler, DOM dom, int node)
    {
        try {
            // Get prefix from qname
            String prefix;
            final int index = qname.indexOf(':');
            
            if (index > 0) {
                prefix = qname.substring(0, index);
                
                // Handle case when prefix is not known at compile time
                if (namespace == null || namespace.length() == 0) {
                    runTimeError(NAMESPACE_PREFIX_ERR,prefix);
                }
                
                handler.startElement(namespace, qname.substring(index+1),
                                         qname);
                handler.namespaceAfterStartElement(prefix, namespace); 
            }
            else {                      
                // Need to generate a prefix?
                if (namespace != null && namespace.length() > 0) {
                    prefix = generatePrefix();
                    qname = prefix + ':' + qname;   
                    handler.startElement(namespace, qname, qname);   
                    handler.namespaceAfterStartElement(prefix, namespace);
                }
                else {
                    handler.startElement(null, null, qname);   
                }
            }
        }
        catch (SAXException e) {
            throw new RuntimeException(e.getMessage());
        }
    
        return qname;
    }    
 
    /**
     * <p>Look up the namespace for a lexical QName using the namespace
     * declarations available at a particular location in the stylesheet.</p>
     * <p>See {@link org.apache.xalan.xsltc.compiler.Stylesheet#compileStaticInitializer(org.apache.xalan.xsltc.compiler.util.ClassGenerator)}
     * for more information about the <code>ancestorNodeIDs</code>,
     * <code>prefixURIsIndex</code> and <code>prefixURIPairs</code arrays.</p>
     *
     * @param lexicalQName The QName as a <code>java.lang.String</code>
     * @param stylesheetNodeID An <code>int</code> representing the element in
     *                     the stylesheet relative to which the namespace of
     *                     the lexical QName is to be determined
     * @param ancestorNodeIDs An <code>int</code> array, indexed by stylesheet
     *                     node IDs, containing the ID of the nearest ancestor
     *                     node in the stylesheet that has namespace
     *                     declarations, or <code>-1</code> if there is no
     *                     such ancestor
     * @param prefixURIsIndex An <code>int</code> array, indexed by stylesheet
     *                     node IDs, containing the index into the
     *                     <code>prefixURIPairs</code> array of the first
     *                     prefix declared on that stylesheet node
     * @param prefixURIPairs A <code>java.lang.String</code> array that contains
     *                     pairs of 
     * @param ignoreDefault A <code>boolean</code> indicating whether any
     *                     default namespace decarlation should be considered
     * @return The namespace of the lexical QName or a zero-length string if
     *         the QName is in no namespace or no namespace declaration for the
     *         prefix of the QName was found
     */
    public static String lookupStylesheetQNameNamespace(String lexicalQName,
                                                        int stylesheetNodeID,
                                                        int[] ancestorNodeIDs,
                                                        int[] prefixURIsIndex,
                                                        String[] prefixURIPairs,
                                                        boolean ignoreDefault) {
        String prefix = getPrefix(lexicalQName);
        String uri = "";

        if (prefix == null && !ignoreDefault) {
            prefix = "";
        }

        if (prefix != null) {
            // Loop from current node in the stylesheet to its ancestors
            nodeLoop:
            for (int currentNodeID = stylesheetNodeID;
                 currentNodeID >= 0;
                 currentNodeID = ancestorNodeIDs[currentNodeID]) {
                // Look at all declarations on the current stylesheet node
                // The prefixURIsIndex is an array of indices into the
                // prefixURIPairs array that are stored in ascending order.
                // The declarations for a node I are in elements
                // prefixURIsIndex[I] to prefixURIsIndex[I+1]-1 (or 
                // prefixURIPairs.length-1 if I is the last node)
                int prefixStartIdx = prefixURIsIndex[currentNodeID];
                int prefixLimitIdx = (currentNodeID+1 < prefixURIsIndex.length)
                                         ? prefixURIsIndex[currentNodeID + 1]
                                         : prefixURIPairs.length;

                for (int prefixIdx = prefixStartIdx;
                     prefixIdx < prefixLimitIdx;
                     prefixIdx = prefixIdx + 2) {
                    // Did we find the declaration of our prefix
                    if (prefix.equals(prefixURIPairs[prefixIdx])) {
                        uri = prefixURIPairs[prefixIdx+1];
                        break nodeLoop;
                    }
                }
            }
        }

        return uri;
    }

    /**
     * <p>Look up the namespace for a lexical QName using the namespace
     * declarations available at a particular location in the stylesheet and
     * return the expanded QName</p>
     * <p>See {@link org.apache.xalan.xsltc.compiler.Stylesheet#compileStaticInitializer(org.apache.xalan.xsltc.compiler.util.ClassGenerator)}
     * for more information about the <code>ancestorNodeIDs</code>,
     * <code>prefixURIsIndex</code> and <code>prefixURIPairs</code arrays.</p>
     *
     * @param lexicalQName The QName as a <code>java.lang.String</code>
     * @param stylesheetNodeID An <code>int</code> representing the element in
     *                     the stylesheet relative to which the namespace of
     *                     the lexical QName is to be determined
     * @param ancestorNodeIDs An <code>int</code> array, indexed by stylesheet
     *                     node IDs, containing the ID of the nearest ancestor
     *                     node in the stylesheet that has namespace
     *                     declarations, or <code>-1</code> if there is no
     *                     such ancestor
     * @param prefixURIsIndex An <code>int</code> array, indexed by stylesheet
     *                     node IDs, containing the index into the
     *                     <code>prefixURIPairs</code> array of the first
     *                     prefix declared on that stylesheet node
     * @param prefixURIPairs A <code>java.lang.String</code> array that contains
     *                     pairs of
     * @param ignoreDefault A <code>boolean</code> indicating whether any
     *                     default namespace decarlation should be considered
     * @return The expanded QName in the form "uri:localName" or just
     *         "localName" if the QName is in no namespace or no namespace
     *         declaration for the prefix of the QName was found
     */
    public static String expandStylesheetQNameRef(String lexicalQName,
                                                  int stylesheetNodeID,
                                                  int[] ancestorNodeIDs,
                                                  int[] prefixURIsIndex,
                                                  String[] prefixURIPairs,
                                                  boolean ignoreDefault) {
        String expandedQName;
        String prefix = getPrefix(lexicalQName);
        String localName = (prefix != null)
                               ? lexicalQName.substring(prefix.length()+1)
                               : lexicalQName;
        String uri = lookupStylesheetQNameNamespace(lexicalQName,
                                                    stylesheetNodeID,
                                                    ancestorNodeIDs,
                                                    prefixURIsIndex,
                                                    prefixURIPairs,
                                                    ignoreDefault);

        // Handle case when prefix is not resolved
        if (prefix != null && prefix.length() != 0
               && (uri == null || uri.length() == 0)) {
            runTimeError(NAMESPACE_PREFIX_ERR, prefix);
        }

        if (uri.length() == 0) {
            expandedQName = localName;
        } else {
            expandedQName = uri + ':' + localName;
        }

        return expandedQName;
    }

    /**
     * This function is used in the execution of xsl:element
     */
    public static String getPrefix(String qname) {
	final int index = qname.indexOf(':');
	return (index > 0) ? qname.substring(0, index) : null;
    }

    /**
     * This function is used in the execution of xsl:element
     */
    private static int prefixIndex = 0;		// not thread safe!!
    public static String generatePrefix() {
	return ("ns" + prefixIndex++);
    }

    public static final String RUN_TIME_INTERNAL_ERR =
                                           "RUN_TIME_INTERNAL_ERR";
    public static final String RUN_TIME_COPY_ERR =
                                           "RUN_TIME_COPY_ERR";
    public static final String DATA_CONVERSION_ERR =
                                           "DATA_CONVERSION_ERR";
    public static final String EXTERNAL_FUNC_ERR =
                                           "EXTERNAL_FUNC_ERR";
    public static final String EQUALITY_EXPR_ERR =
                                           "EQUALITY_EXPR_ERR";
    public static final String INVALID_ARGUMENT_ERR =
                                           "INVALID_ARGUMENT_ERR";
    public static final String FORMAT_NUMBER_ERR =
                                           "FORMAT_NUMBER_ERR";
    public static final String ITERATOR_CLONE_ERR =
                                           "ITERATOR_CLONE_ERR";
    public static final String AXIS_SUPPORT_ERR =
                                           "AXIS_SUPPORT_ERR";
    public static final String TYPED_AXIS_SUPPORT_ERR =
                                           "TYPED_AXIS_SUPPORT_ERR";
    public static final String STRAY_ATTRIBUTE_ERR =
                                           "STRAY_ATTRIBUTE_ERR"; 
    public static final String STRAY_NAMESPACE_ERR =
                                           "STRAY_NAMESPACE_ERR";
    public static final String NAMESPACE_PREFIX_ERR =
                                           "NAMESPACE_PREFIX_ERR";
    public static final String DOM_ADAPTER_INIT_ERR =
                                           "DOM_ADAPTER_INIT_ERR";
    public static final String PARSER_DTD_SUPPORT_ERR =
                                           "PARSER_DTD_SUPPORT_ERR";
    public static final String NAMESPACES_SUPPORT_ERR =
                                           "NAMESPACES_SUPPORT_ERR";
    public static final String CANT_RESOLVE_RELATIVE_URI_ERR =
                                           "CANT_RESOLVE_RELATIVE_URI_ERR";
    public static final String UNSUPPORTED_XSL_ERR =
                                           "UNSUPPORTED_XSL_ERR";
    public static final String UNSUPPORTED_EXT_ERR =
                                           "UNSUPPORTED_EXT_ERR";
    public static final String UNKNOWN_TRANSLET_VERSION_ERR =
                                           "UNKNOWN_TRANSLET_VERSION_ERR";
    public static final String INVALID_QNAME_ERR = "INVALID_QNAME_ERR";                                           
    public static final String INVALID_NCNAME_ERR = "INVALID_NCNAME_ERR";
    public static final String UNALLOWED_EXTENSION_FUNCTION_ERR = "UNALLOWED_EXTENSION_FUNCTION_ERR";
    public static final String UNALLOWED_EXTENSION_ELEMENT_ERR = "UNALLOWED_EXTENSION_ELEMENT_ERR";

    // All error messages are localized and are stored in resource bundles.
    private static ResourceBundle m_bundle;
    
    public final static String ERROR_MESSAGES_KEY = "error-messages";

    static {
	String resource = "org.apache.xalan.xsltc.runtime.ErrorMessages";
	m_bundle = ResourceBundle.getBundle(resource);
    }

    /**
     * Print a run-time error message.
     */
    public static void runTimeError(String code) {
	throw new RuntimeException(m_bundle.getString(code));
    }

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

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

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

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

    /**
     * Replace a certain character in a string with a new substring.
     */
    public static String replace(String base, char ch, String str) {
	return (base.indexOf(ch) < 0) ? base : 
	    replace(base, String.valueOf(ch), new String[] { str });
    }

    public static String replace(String base, String delim, String[] str) {
	final int len = base.length();
	final StringBuffer result = new StringBuffer();

	for (int i = 0; i < len; i++) {
	    final char ch = base.charAt(i);
	    final int k = delim.indexOf(ch);

	    if (k >= 0) {
		result.append(str[k]);
	    }
	    else {
		result.append(ch);
	    }
	}
	return result.toString();
    }


    /**
     * Utility method to allow setting parameters of the form
     * {namespaceuri}localName
     * which get mapped to an instance variable in the class
     * Hence  a parameter of the form "{http://foo.bar}xyz"
     * will be replaced with the corresponding values  
     * by the BasisLibrary's utility method mapQNametoJavaName
     * and thus get mapped to legal java variable names 
     */
    public static String mapQNameToJavaName (String base ) {
       return replace(base, ".-:/{}?#%*",
                      new String[] { "$dot$", "$dash$" ,"$colon$", "$slash$",
                                     "","$colon$","$ques$","$hash$","$per$",
                                     "$aster$"});

    }

    //-- End utility functions
}
