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

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import javax.xml.transform.TransformerException;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.ref.DTMNodeIterator;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XRTreeFrag;
import org.apache.xpath.objects.XString;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;

/**
 * Utility class to help resolve method overloading with Xalan XSLT 
 * argument types.
 */
public class MethodResolver
{

  /**
   * Specifies a search for static methods only.
   */
  public static final int STATIC_ONLY         = 1;

  /**
   * Specifies a search for instance methods only.
   */
  public static final int INSTANCE_ONLY       = 2;

  /**
   * Specifies a search for both static and instance methods.
   */
  public static final int STATIC_AND_INSTANCE = 3;

  /**
   * Specifies a Dynamic method search.  If the method being
   * evaluated is a static method, all arguments are used.
   * Otherwise, it is an instance method and only arguments
   * beginning with the second argument are used.
   */
  public static final int DYNAMIC             = 4;

  /**
   * Given a class, figure out the resolution of 
   * the Java Constructor from the XSLT argument types, and perform the 
   * conversion of the arguments.
   * @param classObj the Class of the object to be constructed.
   * @param argsIn An array of XSLT/XPath arguments.
   * @param argsOut An array of the exact size as argsIn, which will be 
   * populated with converted arguments if a suitable method is found.
   * @return A constructor that will work with the argsOut array.
   * @throws TransformerException may be thrown for Xalan conversion
   * exceptions.
   */
  public static Constructor getConstructor(Class classObj, 
                                           Object[] argsIn, 
                                           Object[][] argsOut,
                                           ExpressionContext exprContext)
    throws NoSuchMethodException,
           SecurityException,
           TransformerException
  {
    Constructor bestConstructor = null;
    Class[] bestParamTypes = null;
    Constructor[] constructors = classObj.getConstructors();
    int nMethods = constructors.length;
    int bestScore = Integer.MAX_VALUE;
    int bestScoreCount = 0;
    for(int i = 0; i < nMethods; i++)
    {
      Constructor ctor = constructors[i];
      Class[] paramTypes = ctor.getParameterTypes();
      int numberMethodParams = paramTypes.length;
      int paramStart = 0;
      boolean isFirstExpressionContext = false;
      int scoreStart;
      // System.out.println("numberMethodParams: "+numberMethodParams);
      // System.out.println("argsIn.length: "+argsIn.length);
      // System.out.println("exprContext: "+exprContext);
      if(numberMethodParams == (argsIn.length+1))
      {
        Class javaClass = paramTypes[0];
        // System.out.println("first javaClass: "+javaClass.getName());
        if(ExpressionContext.class.isAssignableFrom(javaClass))
        {
          isFirstExpressionContext = true;
          scoreStart = 0;
          paramStart++;
          // System.out.println("Incrementing paramStart: "+paramStart);
        }
        else
          continue;
      }
      else
          scoreStart = 1000;
      
      if(argsIn.length == (numberMethodParams - paramStart))
      {
        // then we have our candidate.
        int score = scoreMatch(paramTypes, paramStart, argsIn, scoreStart);
        // System.out.println("score: "+score);
        if(-1 == score)	
          continue;
        if(score < bestScore)
        {
          // System.out.println("Assigning best ctor: "+ctor);
          bestConstructor = ctor;
          bestParamTypes = paramTypes;
          bestScore = score;
          bestScoreCount = 1;
        }
        else if (score == bestScore)
          bestScoreCount++;
      }
    }

    if(null == bestConstructor)
    {
      throw new NoSuchMethodException(errString("function", "constructor", classObj,
                                                                        "", 0, argsIn));
    }
    /*** This is commented out until we can do a better object -> object scoring 
    else if (bestScoreCount > 1)
      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_MORE_MATCH_CONSTRUCTOR, new Object[]{classObj.getName()})); //"More than one best match for constructor for "
                                                                   + classObj.getName());
    ***/
    else
      convertParams(argsIn, argsOut, bestParamTypes, exprContext);
    
    return bestConstructor;
  }

  
  /**
   * Given the name of a method, figure out the resolution of 
   * the Java Method from the XSLT argument types, and perform the 
   * conversion of the arguments.
   * @param classObj The Class of the object that should have the method.
   * @param name The name of the method to be invoked.
   * @param argsIn An array of XSLT/XPath arguments.
   * @param argsOut An array of the exact size as argsIn, which will be 
   * populated with converted arguments if a suitable method is found.
   * @return A method that will work with the argsOut array.
   * @throws TransformerException may be thrown for Xalan conversion
   * exceptions.
   */
  public static Method getMethod(Class classObj,
                                 String name, 
                                 Object[] argsIn, 
                                 Object[][] argsOut,
                                 ExpressionContext exprContext,
                                 int searchMethod)
    throws NoSuchMethodException,
           SecurityException,
           TransformerException
  {
    // System.out.println("---> Looking for method: "+name);
    // System.out.println("---> classObj: "+classObj);
    if (name.indexOf("-")>0)
      name = replaceDash(name);
    Method bestMethod = null;
    Class[] bestParamTypes = null;
    Method[] methods = classObj.getMethods();
    int nMethods = methods.length;
    int bestScore = Integer.MAX_VALUE;
    int bestScoreCount = 0;
    boolean isStatic;
    for(int i = 0; i < nMethods; i++)
    {
      Method method = methods[i];
      // System.out.println("looking at method: "+method);
      int xsltParamStart = 0;
      if(method.getName().equals(name))
      {
        isStatic = Modifier.isStatic(method.getModifiers());
        switch(searchMethod)
        {
          case STATIC_ONLY:
            if (!isStatic)
            {
              continue;
            }
            break;

          case INSTANCE_ONLY:
            if (isStatic)
            {
              continue;
            }
            break;

          case STATIC_AND_INSTANCE:
            break;

          case DYNAMIC:
            if (!isStatic)
              xsltParamStart = 1;
        }
        int javaParamStart = 0;
        Class[] paramTypes = method.getParameterTypes();
        int numberMethodParams = paramTypes.length;
        boolean isFirstExpressionContext = false;
        int scoreStart;
        // System.out.println("numberMethodParams: "+numberMethodParams);
        // System.out.println("argsIn.length: "+argsIn.length);
        // System.out.println("exprContext: "+exprContext);
        int argsLen = (null != argsIn) ? argsIn.length : 0;
        if(numberMethodParams == (argsLen-xsltParamStart+1))
        {
          Class javaClass = paramTypes[0];
          if(ExpressionContext.class.isAssignableFrom(javaClass))
          {
            isFirstExpressionContext = true;
            scoreStart = 0;
            javaParamStart++;
          }
          else
          {
            continue;
          }
        }
        else
            scoreStart = 1000;
        
        if((argsLen - xsltParamStart) == (numberMethodParams - javaParamStart))
        {
          // then we have our candidate.
          int score = scoreMatch(paramTypes, javaParamStart, argsIn, scoreStart);
          // System.out.println("score: "+score);
          if(-1 == score)
            continue;
          if(score < bestScore)
          {
            // System.out.println("Assigning best method: "+method);
            bestMethod = method;
            bestParamTypes = paramTypes;
            bestScore = score;
            bestScoreCount = 1;
          }
          else if (score == bestScore)
            bestScoreCount++;
        }
      }
    }
    
    if (null == bestMethod)
    {
      throw new NoSuchMethodException(errString("function", "method", classObj,
                                                                name, searchMethod, argsIn));
    }
    /*** This is commented out until we can do a better object -> object scoring 
    else if (bestScoreCount > 1)
      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_MORE_MATCH_METHOD, new Object[]{name})); //"More than one best match for method " + name);
    ***/
    else
      convertParams(argsIn, argsOut, bestParamTypes, exprContext);
    
    return bestMethod;
  }
  
  /**
   * To support EXSLT extensions, convert names with dash to allowable Java names: 
   * e.g., convert abc-xyz to abcXyz.
   * Note: dashes only appear in middle of an EXSLT function or element name.
   */
  private static String replaceDash(String name)
  {
    char dash = '-';
    StringBuffer buff = new StringBuffer("");
    for (int i=0; i<name.length(); i++)
    {
      if (name.charAt(i) == dash)
      {}
      else if (i > 0 && name.charAt(i-1) == dash)
        buff.append(Character.toUpperCase(name.charAt(i)));
      else
        buff.append(name.charAt(i));
    }
    return buff.toString();
  }
  
  /**
   * Given the name of a method, figure out the resolution of 
   * the Java Method
   * @param classObj The Class of the object that should have the method.
   * @param name The name of the method to be invoked.
   * @return A method that will work to be called as an element.
   * @throws TransformerException may be thrown for Xalan conversion
   * exceptions.
   */
  public static Method getElementMethod(Class classObj,
                                        String name)
    throws NoSuchMethodException,
           SecurityException,
           TransformerException
  {
    // System.out.println("---> Looking for element method: "+name);
    // System.out.println("---> classObj: "+classObj);
    Method bestMethod = null;
    Method[] methods = classObj.getMethods();
    int nMethods = methods.length;
    int bestScoreCount = 0;
    for(int i = 0; i < nMethods; i++)
    {
      Method method = methods[i];
      // System.out.println("looking at method: "+method);
      if(method.getName().equals(name))
      {
        Class[] paramTypes = method.getParameterTypes();
        if ( (paramTypes.length == 2)
           && paramTypes[1].isAssignableFrom(org.apache.xalan.templates.ElemExtensionCall.class)
                                         && paramTypes[0].isAssignableFrom(org.apache.xalan.extensions.XSLProcessorContext.class) )
        {
          if ( ++bestScoreCount == 1 )
            bestMethod = method;
          else
            break;
        }
      }
    }
    
    if (null == bestMethod)
    {
      throw new NoSuchMethodException(errString("element", "method", classObj,
                                                                        name, 0, null));
    }
    else if (bestScoreCount > 1)
      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_MORE_MATCH_ELEMENT, new Object[]{name})); //"More than one best match for element method " + name);
    
    return bestMethod;
  }
  

  /**
   * Convert a set of parameters based on a set of paramTypes.
   * @param argsIn An array of XSLT/XPath arguments.
   * @param argsOut An array of the exact size as argsIn, which will be 
   * populated with converted arguments.
   * @param paramTypes An array of class objects, of the exact same 
   * size as argsIn and argsOut.
   * @throws TransformerException may be thrown for Xalan conversion
   * exceptions.
   */
  public static void convertParams(Object[] argsIn, 
                                   Object[][] argsOut, Class[] paramTypes,
                                   ExpressionContext exprContext)
    throws javax.xml.transform.TransformerException
  {
    // System.out.println("In convertParams");
    if (paramTypes == null)
      argsOut[0] = null;
    else
    {
      int nParams = paramTypes.length;
      argsOut[0] = new Object[nParams];
      int paramIndex = 0;
      if((nParams > 0) 
         && ExpressionContext.class.isAssignableFrom(paramTypes[0]))
      {
        argsOut[0][0] = exprContext;
        // System.out.println("Incrementing paramIndex in convertParams: "+paramIndex);
        paramIndex++;
      }

      if (argsIn != null)
      {
        for(int i = argsIn.length - nParams + paramIndex ; paramIndex < nParams; i++, paramIndex++)
        {
          // System.out.println("paramTypes[i]: "+paramTypes[i]);
          argsOut[0][paramIndex] = convert(argsIn[i], paramTypes[paramIndex]);
        }
      }
    }
  }
  
  /**
   * Simple class to hold information about allowed conversions 
   * and their relative scores, for use by the table below.
   */
  static class ConversionInfo
  {
    ConversionInfo(Class cl, int score)
    {
      m_class = cl;
      m_score = score;
    }
    
    Class m_class;  // Java class to convert to.
    int m_score; // Match score, closer to zero is more matched.
  }
  
  private static final int SCOREBASE=1;
  
  /**
   * Specification of conversions from XSLT type CLASS_UNKNOWN
   * (i.e. some unknown Java object) to allowed Java types.
   */
  static ConversionInfo[] m_javaObjConversions = {
    new ConversionInfo(Double.TYPE, 11),
    new ConversionInfo(Float.TYPE, 12),
    new ConversionInfo(Long.TYPE, 13),
    new ConversionInfo(Integer.TYPE, 14),
    new ConversionInfo(Short.TYPE, 15),
    new ConversionInfo(Character.TYPE, 16),
    new ConversionInfo(Byte.TYPE, 17),
    new ConversionInfo(java.lang.String.class, 18)
  };
  
  /**
   * Specification of conversions from XSLT type CLASS_BOOLEAN
   * to allowed Java types.
   */
  static ConversionInfo[] m_booleanConversions = {
    new ConversionInfo(Boolean.TYPE, 0),
    new ConversionInfo(java.lang.Boolean.class, 1),
    new ConversionInfo(java.lang.Object.class, 2),
    new ConversionInfo(java.lang.String.class, 3)
  };

  /**
   * Specification of conversions from XSLT type CLASS_NUMBER
   * to allowed Java types.
   */
  static ConversionInfo[] m_numberConversions = {
    new ConversionInfo(Double.TYPE, 0),
    new ConversionInfo(java.lang.Double.class, 1),
    new ConversionInfo(Float.TYPE, 3),
    new ConversionInfo(Long.TYPE, 4),
    new ConversionInfo(Integer.TYPE, 5),
    new ConversionInfo(Short.TYPE, 6),
    new ConversionInfo(Character.TYPE, 7),
    new ConversionInfo(Byte.TYPE, 8),
    new ConversionInfo(Boolean.TYPE, 9),
    new ConversionInfo(java.lang.String.class, 10),
    new ConversionInfo(java.lang.Object.class, 11)
  };

  /**
   * Specification of conversions from XSLT type CLASS_STRING
   * to allowed Java types.
   */
  static ConversionInfo[] m_stringConversions = {
    new ConversionInfo(java.lang.String.class, 0),
    new ConversionInfo(java.lang.Object.class, 1),
    new ConversionInfo(Character.TYPE, 2),
    new ConversionInfo(Double.TYPE, 3),
    new ConversionInfo(Float.TYPE, 3),
    new ConversionInfo(Long.TYPE, 3),
    new ConversionInfo(Integer.TYPE, 3),
    new ConversionInfo(Short.TYPE, 3),
    new ConversionInfo(Byte.TYPE, 3),
    new ConversionInfo(Boolean.TYPE, 4)
  };

  /**
   * Specification of conversions from XSLT type CLASS_RTREEFRAG
   * to allowed Java types.
   */
  static ConversionInfo[] m_rtfConversions = {
    new ConversionInfo(org.w3c.dom.traversal.NodeIterator.class, 0),
    new ConversionInfo(org.w3c.dom.NodeList.class, 1),
    new ConversionInfo(org.w3c.dom.Node.class, 2),
    new ConversionInfo(java.lang.String.class, 3),
    new ConversionInfo(java.lang.Object.class, 5),
    new ConversionInfo(Character.TYPE, 6),
    new ConversionInfo(Double.TYPE, 7),
    new ConversionInfo(Float.TYPE, 7),
    new ConversionInfo(Long.TYPE, 7),
    new ConversionInfo(Integer.TYPE, 7),
    new ConversionInfo(Short.TYPE, 7),
    new ConversionInfo(Byte.TYPE, 7),
    new ConversionInfo(Boolean.TYPE, 8)
  };
  
  /**
   * Specification of conversions from XSLT type CLASS_NODESET
   * to allowed Java types.  (This is the same as for CLASS_RTREEFRAG)
   */
  static ConversionInfo[] m_nodesetConversions = {
    new ConversionInfo(org.w3c.dom.traversal.NodeIterator.class, 0),
    new ConversionInfo(org.w3c.dom.NodeList.class, 1),
    new ConversionInfo(org.w3c.dom.Node.class, 2),
    new ConversionInfo(java.lang.String.class, 3),
    new ConversionInfo(java.lang.Object.class, 5),
    new ConversionInfo(Character.TYPE, 6),
    new ConversionInfo(Double.TYPE, 7),
    new ConversionInfo(Float.TYPE, 7),
    new ConversionInfo(Long.TYPE, 7),
    new ConversionInfo(Integer.TYPE, 7),
    new ConversionInfo(Short.TYPE, 7),
    new ConversionInfo(Byte.TYPE, 7),
    new ConversionInfo(Boolean.TYPE, 8)
  };
  
  /**
   * Order is significant in the list below, based on 
   * XObject.CLASS_XXX values.
   */
  static ConversionInfo[][] m_conversions = 
  {
    m_javaObjConversions, // CLASS_UNKNOWN = 0;
    m_booleanConversions, // CLASS_BOOLEAN = 1;
    m_numberConversions,  // CLASS_NUMBER = 2;
    m_stringConversions,  // CLASS_STRING = 3;
    m_nodesetConversions, // CLASS_NODESET = 4;
    m_rtfConversions      // CLASS_RTREEFRAG = 5;
  };
  
  /**
   * Score the conversion of a set of XSLT arguments to a 
   * given set of Java parameters.
   * If any invocations of this function for a method with 
   * the same name return the same positive value, then a conflict 
   * has occured, and an error should be signaled.
   * @param javaParamTypes Must be filled with valid class names, and 
   * of the same length as xsltArgs.
   * @param xsltArgs Must be filled with valid object instances, and 
   * of the same length as javeParamTypes.
   * @return -1 for no allowed conversion, or a positive score 
   * that is closer to zero for more preferred, or further from 
   * zero for less preferred.
   */
  public static int scoreMatch(Class[] javaParamTypes, int javaParamsStart,
                               Object[] xsltArgs, int score)
  {
    if ((xsltArgs == null) || (javaParamTypes == null))
      return score;
    int nParams = xsltArgs.length;
    for(int i = nParams - javaParamTypes.length + javaParamsStart, javaParamTypesIndex = javaParamsStart; 
        i < nParams; 
        i++, javaParamTypesIndex++)
    {
      Object xsltObj = xsltArgs[i];
      int xsltClassType = (xsltObj instanceof XObject) 
                          ? ((XObject)xsltObj).getType() 
                            : XObject.CLASS_UNKNOWN;
      Class javaClass = javaParamTypes[javaParamTypesIndex];
      
      // System.out.println("Checking xslt: "+xsltObj.getClass().getName()+
      //                   " against java: "+javaClass.getName());
      
      if(xsltClassType == XObject.CLASS_NULL)
      {
        // In Xalan I have objects of CLASS_NULL, though I'm not 
        // sure they're used any more.  For now, do something funky.
        if(!javaClass.isPrimitive())
        {
          // Then assume that a null can be used, but give it a low score.
          score += 10;
          continue;
        }
        else
          return -1;  // no match.
      }
      
      ConversionInfo[] convInfo = m_conversions[xsltClassType];
      int nConversions = convInfo.length;
      int k;
      for(k = 0; k < nConversions; k++)
      {
        ConversionInfo cinfo = convInfo[k];
        if(javaClass.isAssignableFrom(cinfo.m_class))
        {
          score += cinfo.m_score;
          break; // from k loop
        }
      }

      if (k == nConversions)
      {
        // If we get here, we haven't made a match on this parameter using 
        // the ConversionInfo array.  We now try to handle the object -> object
        // mapping which we can't handle through the array mechanism.  To do this,
        // we must determine the class of the argument passed from the stylesheet.

        // If we were passed a subclass of XObject, representing one of the actual
        // XSLT types, and we are here, we reject this extension method as a candidate
        // because a match should have been made using the ConversionInfo array.  If we 
        // were passed an XObject that encapsulates a non-XSLT type or we
        // were passed a non-XSLT type directly, we continue.

        // The current implementation (contributed by Kelly Campbell <camk@channelpoint.com>)
        // checks to see if we were passed an XObject from the XSLT stylesheet.  If not,
        // we use the class of the object that was passed and make sure that it will
        // map to the class type of the parameter in the extension function.
        // If we were passed an XObject, we attempt to get the class of the actual
        // object encapsulated inside the XObject.  If the encapsulated object is null,
        // we judge this method as a match but give it a low score.  
        // If the encapsulated object is not null, we use its type to determine
        // whether this java method is a valid match for this extension function call.
        // This approach eliminates the NullPointerException in the earlier implementation
        // that resulted from passing an XObject encapsulating the null java object.
                                
        // TODO:  This needs to be improved to assign relative scores to subclasses,
        // etc. 

        if (XObject.CLASS_UNKNOWN == xsltClassType)
        {
          Class realClass = null;

          if (xsltObj instanceof XObject)
          {
            Object realObj = ((XObject) xsltObj).object();
            if (null != realObj)
            {
              realClass = realObj.getClass();
            }
            else
            {
              // do the same as if we were passed XObject.CLASS_NULL
              score += 10;
              continue;
            }
          }
          else
          {
            realClass = xsltObj.getClass();
          }

          if (javaClass.isAssignableFrom(realClass))
          {
            score += 0;         // TODO: To be assigned based on subclass "distance"
          }
          else
            return -1;
        }
        else
          return -1;
      }
    }
    return score;
  }
  
  /**
   * Convert the given XSLT object to an object of 
   * the given class.
   * @param xsltObj The XSLT object that needs conversion.
   * @param javaClass The type of object to convert to.
   * @returns An object suitable for passing to the Method.invoke 
   * function in the args array, which may be null in some cases.
   * @throws TransformerException may be thrown for Xalan conversion
   * exceptions.
   */
  static Object convert(Object xsltObj, Class javaClass)
    throws javax.xml.transform.TransformerException
  {
    if(xsltObj instanceof XObject)
    {
      XObject xobj = ((XObject)xsltObj);
      int xsltClassType = xobj.getType();

      switch(xsltClassType)
      {
      case XObject.CLASS_NULL:
        return null;
        
      case XObject.CLASS_BOOLEAN:
        {
          if(javaClass == java.lang.String.class)
            return xobj.str();
          else
            return new Boolean(xobj.bool());
        }
        // break; Unreachable
      case XObject.CLASS_NUMBER:
        {
          if(javaClass == java.lang.String.class)
            return xobj.str();
          else if(javaClass == Boolean.TYPE)
            return new Boolean(xobj.bool());
          else 
          {
            return convertDoubleToNumber(xobj.num(), javaClass);
          }
        }
        // break; Unreachable
        
      case XObject.CLASS_STRING:
        {
          if((javaClass == java.lang.String.class) ||
             (javaClass == java.lang.Object.class))
            return xobj.str();
          else if(javaClass == Character.TYPE)
          {
            String str = xobj.str();
            if(str.length() > 0)
              return new Character(str.charAt(0));
            else
              return null; // ??
          }
          else if(javaClass == Boolean.TYPE)
            return new Boolean(xobj.bool());
          else 
          {
            return convertDoubleToNumber(xobj.num(), javaClass);
          }
        }
        // break; Unreachable
        
      case XObject.CLASS_RTREEFRAG:
        {
          // GLP:  I don't see the reason for the isAssignableFrom call
          //       instead of an == test as is used everywhere else.
          //       Besides, if the javaClass is a subclass of NodeIterator
          //       the condition will be true and we'll create a NodeIterator
          //       which may not match the javaClass, causing a RuntimeException.
          // if((NodeIterator.class.isAssignableFrom(javaClass)) ||
          if ( (javaClass == NodeIterator.class) ||
               (javaClass == java.lang.Object.class) )
          {
            DTMIterator dtmIter = ((XRTreeFrag) xobj).asNodeIterator();
            return new DTMNodeIterator(dtmIter);
          }
          else if (javaClass == NodeList.class)
          {
            return ((XRTreeFrag) xobj).convertToNodeset();
          }
          // Same comment as above
          // else if(Node.class.isAssignableFrom(javaClass))
          else if(javaClass == Node.class)
          {
            DTMIterator iter = ((XRTreeFrag) xobj).asNodeIterator();
            int rootHandle = iter.nextNode();
            DTM dtm = iter.getDTM(rootHandle);
            return dtm.getNode(dtm.getFirstChild(rootHandle));
          }
          else if(javaClass == java.lang.String.class)
          {
            return xobj.str();
          }
          else if(javaClass == Boolean.TYPE)
          {
            return new Boolean(xobj.bool());
          }
          else if(javaClass.isPrimitive())
          {
            return convertDoubleToNumber(xobj.num(), javaClass);
          }
          else
          {
            DTMIterator iter = ((XRTreeFrag) xobj).asNodeIterator();
            int rootHandle = iter.nextNode();
            DTM dtm = iter.getDTM(rootHandle);
            Node child = dtm.getNode(dtm.getFirstChild(rootHandle));

            if(javaClass.isAssignableFrom(child.getClass()))
              return child;
            else
              return null;
          }
        }
        // break; Unreachable
        
      case XObject.CLASS_NODESET:
        {
          // GLP:  I don't see the reason for the isAssignableFrom call
          //       instead of an == test as is used everywhere else.
          //       Besides, if the javaClass is a subclass of NodeIterator
          //       the condition will be true and we'll create a NodeIterator
          //       which may not match the javaClass, causing a RuntimeException.
          // if((NodeIterator.class.isAssignableFrom(javaClass)) ||
          if ( (javaClass == NodeIterator.class) ||
               (javaClass == java.lang.Object.class) )
          {
            return xobj.nodeset();
          }
          // Same comment as above
          // else if(NodeList.class.isAssignableFrom(javaClass))
          else if(javaClass == NodeList.class)
          {
            return xobj.nodelist();
          }
          // Same comment as above
          // else if(Node.class.isAssignableFrom(javaClass))
          else if(javaClass == Node.class)
          {
            // Xalan ensures that iter() always returns an
            // iterator positioned at the beginning.
            DTMIterator ni = xobj.iter();
            int handle = ni.nextNode();
            if (handle != DTM.NULL)
              return ni.getDTM(handle).getNode(handle); // may be null.
            else
              return null;
          }
          else if(javaClass == java.lang.String.class)
          {
            return xobj.str();
          }
          else if(javaClass == Boolean.TYPE)
          {
            return new Boolean(xobj.bool());
          }
          else if(javaClass.isPrimitive())
          {
            return convertDoubleToNumber(xobj.num(), javaClass);
          }
          else
          {
            DTMIterator iter = xobj.iter();
            int childHandle = iter.nextNode();
            DTM dtm = iter.getDTM(childHandle);
            Node child = dtm.getNode(childHandle);
            if(javaClass.isAssignableFrom(child.getClass()))
              return child;
            else
              return null;
          }
        }
        // break; Unreachable
        
        // No default:, fall-through on purpose
      } // end switch
      xsltObj = xobj.object();
      
    } // end if if(xsltObj instanceof XObject)
    
    // At this point, we have a raw java object, not an XObject.
    if (null != xsltObj)
    {
      if(javaClass == java.lang.String.class)
      {
        return xsltObj.toString();
      }
      else if(javaClass.isPrimitive())
      {
        // Assume a number conversion
        XString xstr = new XString(xsltObj.toString());
        double num = xstr.num();
        return convertDoubleToNumber(num, javaClass);
      }
      else if(javaClass == java.lang.Class.class)
      {
        return xsltObj.getClass();
      }
      else
      {
        // Just pass the object directly, and hope for the best.
        return xsltObj;
      }
                }
    else
    {
      // Just pass the object directly, and hope for the best.
      return xsltObj;
    }
  }
  
  /**
   * Do a standard conversion of a double to the specified type.
   * @param num The number to be converted.
   * @param javaClass The class type to be converted to.
   * @return An object specified by javaClass, or a Double instance.
   */
  static Object convertDoubleToNumber(double num, Class javaClass)
  {
    // In the code below, I don't check for NaN, etc., instead 
    // using the standard Java conversion, as I think we should 
    // specify.  See issue-runtime-errors.
    if((javaClass == Double.TYPE) ||
       (javaClass == java.lang.Double.class))
      return new Double(num);
    else if(javaClass == Float.TYPE)
      return new Float(num);
    else if(javaClass == Long.TYPE)
    {
      // Use standard Java Narrowing Primitive Conversion
      // See http://java.sun.com/docs/books/jls/html/5.doc.html#175672
      return new Long((long)num);
    }
    else if(javaClass == Integer.TYPE)
    {
      // Use standard Java Narrowing Primitive Conversion
      // See http://java.sun.com/docs/books/jls/html/5.doc.html#175672
      return new Integer((int)num);
    }
    else if(javaClass == Short.TYPE)
    {
      // Use standard Java Narrowing Primitive Conversion
      // See http://java.sun.com/docs/books/jls/html/5.doc.html#175672
      return new Short((short)num);
    }
    else if(javaClass == Character.TYPE)
    {
      // Use standard Java Narrowing Primitive Conversion
      // See http://java.sun.com/docs/books/jls/html/5.doc.html#175672
      return new Character((char)num);
    }
    else if(javaClass == Byte.TYPE)
    {
      // Use standard Java Narrowing Primitive Conversion
      // See http://java.sun.com/docs/books/jls/html/5.doc.html#175672
      return new Byte((byte)num);
    }
    else     // Some other type of object
    {
      return new Double(num);
    }
  }


  /**
   * Format the message for the NoSuchMethodException containing 
   * all the information about the method we're looking for.
   */
  private static String errString(String callType,    // "function" or "element"
                                  String searchType,  // "method" or "constructor"
                                  Class classObj,
                                  String funcName,
                                  int searchMethod,
                                  Object[] xsltArgs)
  {
    String resultString = "For extension " + callType
                                              + ", could not find " + searchType + " ";
    switch (searchMethod)
    {
      case STATIC_ONLY:
        return resultString + "static " + classObj.getName() + "." 
                            + funcName + "([ExpressionContext,] " + errArgs(xsltArgs, 0) + ").";

      case INSTANCE_ONLY:
        return resultString + classObj.getName() + "."
                            + funcName + "([ExpressionContext,] " + errArgs(xsltArgs, 0) + ").";

      case STATIC_AND_INSTANCE:
        return resultString + classObj.getName() + "." + funcName + "([ExpressionContext,] " + errArgs(xsltArgs, 0) + ").\n"
                            + "Checked both static and instance methods.";

      case DYNAMIC:
        return resultString + "static " + classObj.getName() + "." + funcName
                            + "([ExpressionContext, ]" + errArgs(xsltArgs, 0) + ") nor\n"
                            + classObj + "." + funcName + "([ExpressionContext,] " + errArgs(xsltArgs, 1) + ").";

      default:
        if (callType.equals("function"))      // must be a constructor
        {
          return resultString + classObj.getName()
                                  + "([ExpressionContext,] " + errArgs(xsltArgs, 0) + ").";
        }
        else                                  // must be an element call
        {
          return resultString + classObj.getName() + "." + funcName
                    + "(org.apache.xalan.extensions.XSLProcessorContext, "
                    + "org.apache.xalan.templates.ElemExtensionCall).";
        }
    }
    
  }


  private static String errArgs(Object[] xsltArgs, int startingArg)
  {
    StringBuffer returnArgs = new StringBuffer();
    for (int i = startingArg; i < xsltArgs.length; i++)
    {
      if (i != startingArg)
        returnArgs.append(", ");
      if (xsltArgs[i] instanceof XObject)
        returnArgs.append(((XObject) xsltArgs[i]).getTypeString());      
      else
        returnArgs.append(xsltArgs[i].getClass().getName());
    }
    return returnArgs.toString();
  }

}
