Home | History | Annotate | Download | only in templates
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: ElemWithParam.java 468643 2006-10-28 06:56:03Z minchau $
     20  */
     21 package org.apache.xalan.templates;
     22 
     23 import javax.xml.transform.TransformerException;
     24 
     25 import org.apache.xalan.res.XSLTErrorResources;
     26 import org.apache.xalan.transformer.TransformerImpl;
     27 import org.apache.xml.utils.QName;
     28 import org.apache.xpath.XPath;
     29 import org.apache.xpath.XPathContext;
     30 import org.apache.xpath.objects.XObject;
     31 import org.apache.xpath.objects.XRTreeFrag;
     32 import org.apache.xpath.objects.XString;
     33 
     34 /**
     35  * Implement xsl:with-param.  xsl:with-param is allowed within
     36  * both xsl:call-template and xsl:apply-templates.
     37  * <pre>
     38  * <!ELEMENT xsl:with-param %template;>
     39  * <!ATTLIST xsl:with-param
     40  *   name %qname; #REQUIRED
     41  *   select %expr; #IMPLIED
     42  * >
     43  * </pre>
     44  * @see <a href="http://www.w3.org/TR/xslt#element-with-param">element-with-param in XSLT Specification</a>
     45  * @xsl.usage advanced
     46  */
     47 public class ElemWithParam extends ElemTemplateElement
     48 {
     49     static final long serialVersionUID = -1070355175864326257L;
     50   /**
     51    * This is the index to the stack frame being called, <emph>not</emph> the
     52    * stack frame that contains this element.
     53    */
     54   int m_index;
     55 
     56   /**
     57    * The "select" attribute, which specifies the value of the
     58    * argument, if element content is not specified.
     59    * @serial
     60    */
     61   private XPath m_selectPattern = null;
     62 
     63   /**
     64    * Set the "select" attribute.
     65    * The "select" attribute specifies the value of the
     66    * argument, if element content is not specified.
     67    *
     68    * @param v Value to set for the "select" attribute.
     69    */
     70   public void setSelect(XPath v)
     71   {
     72     m_selectPattern = v;
     73   }
     74 
     75   /**
     76    * Get the "select" attribute.
     77    * The "select" attribute specifies the value of the
     78    * argument, if element content is not specified.
     79    *
     80    * @return Value of the "select" attribute.
     81    */
     82   public XPath getSelect()
     83   {
     84     return m_selectPattern;
     85   }
     86 
     87   /**
     88    * The required name attribute specifies the name of the
     89    * parameter (the variable the value of whose binding is
     90    * to be replaced). The value of the name attribute is a QName,
     91    * which is expanded as described in [2.4 Qualified Names].
     92    * @serial
     93    */
     94   private QName m_qname = null;
     95 
     96   int m_qnameID;
     97 
     98   /**
     99    * Set the "name" attribute.
    100    * DJD
    101    *
    102    * @param v Value to set for the "name" attribute.
    103    */
    104   public void setName(QName v)
    105   {
    106     m_qname = v;
    107   }
    108 
    109   /**
    110    * Get the "name" attribute.
    111    * DJD
    112    *
    113    * @return Value of the "name" attribute.
    114    */
    115   public QName getName()
    116   {
    117     return m_qname;
    118   }
    119 
    120   /**
    121    * Get an integer representation of the element type.
    122    *
    123    * @return An integer representation of the element, defined in the
    124    *     Constants class.
    125    * @see org.apache.xalan.templates.Constants
    126    */
    127   public int getXSLToken()
    128   {
    129     return Constants.ELEMNAME_WITHPARAM;
    130   }
    131 
    132 
    133   /**
    134    * Return the node name.
    135    *
    136    * @return the node name.
    137    */
    138   public String getNodeName()
    139   {
    140     return Constants.ELEMNAME_WITHPARAM_STRING;
    141   }
    142 
    143   /**
    144    * This function is called after everything else has been
    145    * recomposed, and allows the template to set remaining
    146    * values that may be based on some other property that
    147    * depends on recomposition.
    148    */
    149   public void compose(StylesheetRoot sroot) throws TransformerException
    150   {
    151     // See if we can reduce an RTF to a select with a string expression.
    152     if(null == m_selectPattern
    153        && sroot.getOptimizer())
    154     {
    155       XPath newSelect = ElemVariable.rewriteChildToExpression(this);
    156       if(null != newSelect)
    157         m_selectPattern = newSelect;
    158     }
    159     m_qnameID = sroot.getComposeState().getQNameID(m_qname);
    160     super.compose(sroot);
    161 
    162     java.util.Vector vnames = sroot.getComposeState().getVariableNames();
    163     if(null != m_selectPattern)
    164       m_selectPattern.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize());
    165 
    166     // m_index must be resolved by ElemApplyTemplates and ElemCallTemplate!
    167   }
    168 
    169   /**
    170    * Set the parent as an ElemTemplateElement.
    171    *
    172    * @param p This node's parent as an ElemTemplateElement
    173    */
    174   public void setParentElem(ElemTemplateElement p)
    175   {
    176     super.setParentElem(p);
    177     p.m_hasVariableDecl = true;
    178   }
    179 
    180   /**
    181    * Get the XObject representation of the variable.
    182    *
    183    * @param transformer non-null reference to the the current transform-time state.
    184    * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
    185    *
    186    * @return the XObject representation of the variable.
    187    *
    188    * @throws TransformerException
    189    */
    190   public XObject getValue(TransformerImpl transformer, int sourceNode)
    191           throws TransformerException
    192   {
    193 
    194     XObject var;
    195     XPathContext xctxt = transformer.getXPathContext();
    196 
    197     xctxt.pushCurrentNode(sourceNode);
    198 
    199     try
    200     {
    201       if (null != m_selectPattern)
    202       {
    203         var = m_selectPattern.execute(xctxt, sourceNode, this);
    204 
    205         var.allowDetachToRelease(false);
    206       }
    207       else if (null == getFirstChildElem())
    208       {
    209         var = XString.EMPTYSTRING;
    210       }
    211       else
    212       {
    213 
    214         // Use result tree fragment
    215         int df = transformer.transformToRTF(this);
    216 
    217         var = new XRTreeFrag(df, xctxt, this);
    218       }
    219     }
    220     finally
    221     {
    222       xctxt.popCurrentNode();
    223     }
    224 
    225     return var;
    226   }
    227 
    228   /**
    229    * Call the children visitors.
    230    * @param visitor The visitor whose appropriate method will be called.
    231    */
    232   protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs)
    233   {
    234   	if(callAttrs && (null != m_selectPattern))
    235   		m_selectPattern.getExpression().callVisitors(m_selectPattern, visitor);
    236     super.callChildVisitors(visitor, callAttrs);
    237   }
    238 
    239   /**
    240    * Add a child to the child list. If the select attribute
    241    * is present, an error will be raised.
    242    *
    243    * @param elem New element to append to this element's children list
    244    *
    245    * @return null if the select attribute was present, otherwise the
    246    * child just added to the child list
    247    */
    248   public ElemTemplateElement appendChild(ElemTemplateElement elem)
    249   {
    250     // cannot have content and select
    251     if (m_selectPattern != null)
    252     {
    253       error(XSLTErrorResources.ER_CANT_HAVE_CONTENT_AND_SELECT,
    254           new Object[]{"xsl:" + this.getNodeName()});
    255       return null;
    256     }
    257     return super.appendChild(elem);
    258   }
    259 
    260 
    261 }
    262