/*
 * 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.xalan.xsltc.dom.ArrayNodeListIterator;
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.Axis;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMAxisIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMDefaultBase;
import org.apache.xml.dtm.ref.DTMNodeProxy;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.utils.XML11Char;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 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);
    }
    
    /**
     * In a perfect world, this would be the implementation for
     * nodeList2Iterator. In reality, though, this causes a
     * ClassCastException in getDTMHandleFromNode because SAXImpl is
     * not an instance of DOM2DTM. So we use the more lengthy
     * implementation below until this issue has been addressed.
     *
     * @see org.apache.xml.dtm.ref.DTMManagerDefault#getDTMHandleFromNode
     */
    private static DTMAxisIterator nodeList2IteratorUsingHandleFromNode(
                                        org.w3c.dom.NodeList nodeList,
                                    	Translet translet, DOM dom)
    {
	final int n = nodeList.getLength();
	final int[] dtmHandles = new int[n];
	DTMManager dtmManager = null;
	if (dom instanceof MultiDOM)
	    dtmManager = ((MultiDOM) dom).getDTMManager();
	for (int i = 0; i < n; ++i) {
	    org.w3c.dom.Node node = nodeList.item(i);
	    int handle;
	    if (dtmManager != null) {
		handle = dtmManager.getDTMHandleFromNode(node);
	    }
	    else if (node instanceof DTMNodeProxy
		     && ((DTMNodeProxy) node).getDTM() == dom) {
		handle = ((DTMNodeProxy) node).getDTMNodeNumber();
	    }
	    else {
		runTimeError(RUN_TIME_INTERNAL_ERR, "need MultiDOM");
		return null;
	    }
	    dtmHandles[i] = handle;
	    System.out.println("Node " + i + " has handle 0x" +
			       Integer.toString(handle, 16));
	}
	return new ArrayNodeListIterator(dtmHandles);
    }

    /**
     * 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) 
    {
	// First pass: build w3c DOM for all nodes not proxied from our DOM.
	//
	// Notice: this looses some (esp. parent) context for these nodes,
	// so some way to wrap the original nodes inside a DTMAxisIterator
	// might be preferable in the long run.
	int n = 0; // allow for change in list length, just in case.
	Document doc = null;
	DTMManager dtmManager = null;
	int[] proxyNodes = new int[nodeList.getLength()];
	if (dom instanceof MultiDOM)
	    dtmManager = ((MultiDOM) dom).getDTMManager();
	for (int i = 0; i < nodeList.getLength(); ++i) {
	    org.w3c.dom.Node node = nodeList.item(i);
	    if (node instanceof DTMNodeProxy) {
		DTMNodeProxy proxy = (DTMNodeProxy)node;
		DTM nodeDTM = proxy.getDTM();
		int handle = proxy.getDTMNodeNumber();
		boolean isOurDOM = (nodeDTM == dom);
		if (!isOurDOM && dtmManager != null) {
		    try {
			isOurDOM = (nodeDTM == dtmManager.getDTM(handle));
		    }
		    catch (ArrayIndexOutOfBoundsException e) {
			// invalid node handle, so definitely not our doc
		    }
		}
		if (isOurDOM) {
		    proxyNodes[i] = handle;
		    ++n;
		    continue;
		}
	    }
	    proxyNodes[i] = DTM.NULL;
	    int nodeType = node.getNodeType();
	    if (doc == null) {
		if (dom instanceof MultiDOM == false) {
		    runTimeError(RUN_TIME_INTERNAL_ERR, "need MultiDOM");
		    return null;
		}
		try {
		    AbstractTranslet at = (AbstractTranslet) translet;
		    doc = at.newDocument("", "__top__");
		}
		catch (javax.xml.parsers.ParserConfigurationException e) {
		    runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
		    return null;
		}
	    }
	    // Use one dummy element as container for each node of the
	    // list. That way, it is easier to detect resp. avoid
	    // funny things which change the number of nodes,
	    // e.g. auto-concatenation of text nodes.
	    Element mid;
	    switch (nodeType) {
		case org.w3c.dom.Node.ELEMENT_NODE:
		case org.w3c.dom.Node.TEXT_NODE:
		case org.w3c.dom.Node.CDATA_SECTION_NODE:
		case org.w3c.dom.Node.COMMENT_NODE:
		case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
		case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
		    mid = doc.createElementNS(null, "__dummy__");
		    mid.appendChild(doc.importNode(node, true));
		    doc.getDocumentElement().appendChild(mid);
		    ++n;
		    break;
		case org.w3c.dom.Node.ATTRIBUTE_NODE:
		    // The mid element also serves as a container for
		    // attributes, avoiding problems with conflicting
		    // attributes or node order.
		    mid = doc.createElementNS(null, "__dummy__");
		    mid.setAttributeNodeNS((Attr)doc.importNode(node, true));
		    doc.getDocumentElement().appendChild(mid);
		    ++n;
		    break;
		default:
		    // Better play it safe for all types we aren't sure we know
		    // how to deal with.
		    runTimeError(RUN_TIME_INTERNAL_ERR,
				 "Don't know how to convert node type "
				 + nodeType);
	    }
	}

        // w3cDOM -> DTM -> DOMImpl
	DTMAxisIterator iter = null, childIter = null, attrIter = null;
	if (doc != null) {
	    final MultiDOM multiDOM = (MultiDOM) dom;
	    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);
            iter = new AbsoluteIterator(
                new StepIterator(iter1, iter2));

 	    iter.setStartNode(DTMDefaultBase.ROOTNODE);

	    childIter = idom.getAxisIterator(Axis.CHILD);
	    attrIter = idom.getAxisIterator(Axis.ATTRIBUTE);
	}

	// Second pass: find DTM handles for every node in the list.
	int[] dtmHandles = new int[n];
	n = 0;
	for (int i = 0; i < nodeList.getLength(); ++i) {
	    if (proxyNodes[i] != DTM.NULL) {
		dtmHandles[n++] = proxyNodes[i];
		continue;
	    }
	    org.w3c.dom.Node node = nodeList.item(i);
	    DTMAxisIterator iter3 = null;
	    int nodeType = node.getNodeType();
	    switch (nodeType) {
		case org.w3c.dom.Node.ELEMENT_NODE:
		case org.w3c.dom.Node.TEXT_NODE:
		case org.w3c.dom.Node.CDATA_SECTION_NODE:
		case org.w3c.dom.Node.COMMENT_NODE:
		case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
		case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
		    iter3 = childIter;
		    break;
		case org.w3c.dom.Node.ATTRIBUTE_NODE:
		    iter3 = attrIter;
		    break;
		default:
		    // Should not happen, as first run should have got all these
		    throw new InternalRuntimeError("Mismatched cases");
	    }
	    if (iter3 != null) {
		iter3.setStartNode(iter.next());
		dtmHandles[n] = iter3.next();
		// For now, play it self and perform extra checks:
		if (dtmHandles[n] == DTMAxisIterator.END)
		    throw new InternalRuntimeError("Expected element missing at " + i);
		if (iter3.next() != DTMAxisIterator.END)
		    throw new InternalRuntimeError("Too many elements at " + i);
		++n;
	    }
	}
	if (n != dtmHandles.length)
	    throw new InternalRuntimeError("Nodes lost in second pass");

	return new ArrayNodeListIterator(dtmHandles);
    }

    /**
     * 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
}
