You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sa...@apache.org on 2003/10/07 17:44:22 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler CastCall.java Parser.java xpath.cup

santiagopg    2003/10/07 08:44:22

  Modified:    java/src/org/apache/xalan/xsltc/compiler Parser.java
                        xpath.cup
  Added:       java/src/org/apache/xalan/xsltc/compiler CastCall.java
  Log:
  Adding a new extension function for XSLTC. Using this extension function, it is
  possible to recover type information lost by the use of xsl:param (see Bugzilla
  19038). Here is an example:
  
  <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:java="http://xml.apache.org/xalan/java"
      xmlns:xsltc="http://xml.apache.org/xalan/xsltc">
  
  <xsl:param name="object"/>
  
  <xsl:template match="/">
      <xsl:value-of select="java:length(xsltc:cast('java.lang.String', $object))"/>
  </xsl:template>
  
  </xsl:stylesheet>
  
  Without using xsltc:cast(), XSLTC will report an error as the type of param
  'object' cannot be determined statically. The type of xsltc:cast() is:
  
  object[T] cast('T', reference | object[R])
  
  where 'T' indicates that the type of the first argument must be a literal
  string. A ClassCastException may be thrown at runtime if R is not convertible
  to T.
  
  I believe we still need a fully-dynamic solution that does not rely on this
  extension function. However, the two solutions can coexists, especially since
  using xsltc:cast() will always be more efficient than any alternative based
  on Java reflection.
  
  Revision  Changes    Path
  1.60      +3 -1      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java
  
  Index: Parser.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java,v
  retrieving revision 1.59
  retrieving revision 1.60
  diff -u -r1.59 -r1.60
  --- Parser.java	14 Aug 2003 16:27:43 -0000	1.59
  +++ Parser.java	7 Oct 2003 15:44:22 -0000	1.60
  @@ -782,6 +782,7 @@
   	MethodType S_SS = new MethodType(Type.String, Type.String, Type.String);
   	MethodType S_DS = new MethodType(Type.String, Type.Real, Type.String);
   	MethodType S_SR = new MethodType(Type.String, Type.String, Type.Real);
  +	MethodType O_SO = new MethodType(Type.Reference, Type.String, Type.Reference);
   
   	MethodType D_SS =
   	    new MethodType(Type.NodeSet, Type.String, Type.String);
  @@ -862,6 +863,7 @@
   	// Extensions
           _symbolTable.addPrimop("nodeset", D_O);
           _symbolTable.addPrimop("objectType", S_O);
  +        _symbolTable.addPrimop("cast", O_SO);
   
   	// Operators +, -, *, /, % defined on real types.
   	_symbolTable.addPrimop("+", R_RR);	
  
  
  
  1.48      +8 -1      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup
  
  Index: xpath.cup
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- xpath.cup	1 Apr 2003 21:09:00 -0000	1.47
  +++ xpath.cup	7 Oct 2003 15:44:22 -0000	1.48
  @@ -122,6 +122,10 @@
             return _parser.getQNameIgnoreDefaultNs(name);
       }    
   
  +    public QName getQName(String namespace, String prefix, String localname) {
  +        return _parser.getQName(namespace, prefix, localname);
  +    }        
  +
       public void setMultiDocument(boolean flag) {
             _xsltc.setMultiDocument(flag);
       }
  @@ -1021,6 +1025,9 @@
   	  }
             else if (fname == parser.getQNameIgnoreDefaultNs("namespace-uri")) {
               RESULT = new NamespaceUriCall(fname, argl);
  +	  }
  +          else if (fname == parser.getQName(Constants.TRANSLET_URI, "xsltc", "cast")) {
  +            RESULT = new CastCall(fname, argl);
   	  }
   	  // Special case for extension function nodeset()
             else if (fname.getLocalPart().equals("nodeset") || fname.getLocalPart().equals("node-set")) {
  
  
  
  1.1                  xml-xalan/java/src/org/apache/xalan/xsltc/compiler/CastCall.java
  
  Index: CastCall.java
  ===================================================================
  /*
   * @(#)$Id: CastCall.java,v 1.1 2003/10/07 15:44:22 santiagopg Exp $
   *
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-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) 2001, Sun
   * Microsystems., http://www.sun.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * @author Santiago Pericas-Geertsen
   *
   */
  
  package org.apache.xalan.xsltc.compiler;
  
  import java.util.Vector;
  
  import org.apache.bcel.generic.ConstantPoolGen;
  import org.apache.bcel.generic.CHECKCAST;
  import org.apache.bcel.generic.InstructionList;
  import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
  import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
  import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
  import org.apache.xalan.xsltc.compiler.util.Type;
  import org.apache.xalan.xsltc.compiler.util.ObjectType;
  import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
  
  final class CastCall extends FunctionCall {
      
      /**
       * Name of the class that is the target of the cast. Must be a 
       * fully-qualified Java class Name.
       */
      private String _className;
  
      /**
       * A reference to the expression being casted.
       */
      private Expression _right;
  
      /**
       * Constructor.
       */
      public CastCall(QName fname, Vector arguments) {
  	super(fname, arguments);
      }
  
      /**
       * Type check the two parameters for this function
       */
      public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  	// Check that the function was passed exactly two arguments
  	if (argumentCount() != 2) {
  	    throw new TypeCheckError(new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR,
                                                    getName(), this));
  	}
  
          // The first argument must be a literal String
  	Expression exp = argument(0);
          if (exp instanceof LiteralExpr) {
              _className = ((LiteralExpr) exp).getValue();
              _type = new ObjectType(_className);
          }
          else {
  	    throw new TypeCheckError(new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR,
                                                    getName(), this));
          }
          
           // Second argument must be of type reference or object
          _right = argument(1);
          Type tright = _right.typeCheck(stable);
          if (tright != Type.Reference && 
              tright instanceof ObjectType == false) 
          {
  	    throw new TypeCheckError(new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
                                                    tright, _type, this));
          }
          
          return _type;
      }
      
      public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  	final ConstantPoolGen cpg = classGen.getConstantPool();
  	final InstructionList il = methodGen.getInstructionList();
  
          _right.translate(classGen, methodGen);
          il.append(new CHECKCAST(cpg.addClass(_className)));
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org