001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: FunctionDef1Arg.java 468655 2006-10-28 07:12:06Z minchau $
020     */
021    package org.apache.xpath.functions;
022    
023    import org.apache.xalan.res.XSLMessages;
024    import org.apache.xml.dtm.DTM;
025    import org.apache.xml.utils.XMLString;
026    import org.apache.xpath.XPathContext;
027    import org.apache.xpath.objects.XString;
028    import org.apache.xpath.res.XPATHErrorResources;
029    
030    /**
031     * Base class for functions that accept one argument that can be defaulted if
032     * not specified.
033     * @xsl.usage advanced
034     */
035    public class FunctionDef1Arg extends FunctionOneArg
036    {
037        static final long serialVersionUID = 2325189412814149264L;
038    
039      /**
040       * Execute the first argument expression that is expected to return a
041       * nodeset.  If the argument is null, then return the current context node.
042       *
043       * @param xctxt Runtime XPath context.
044       *
045       * @return The first node of the executed nodeset, or the current context
046       *         node if the first argument is null.
047       *
048       * @throws javax.xml.transform.TransformerException if an error occurs while
049       *                                   executing the argument expression.
050       */
051      protected int getArg0AsNode(XPathContext xctxt)
052              throws javax.xml.transform.TransformerException
053      {
054    
055        return (null == m_arg0)
056               ? xctxt.getCurrentNode() : m_arg0.asNode(xctxt);
057      }
058      
059      /**
060       * Tell if the expression is a nodeset expression.
061       * @return true if the expression can be represented as a nodeset.
062       */
063      public boolean Arg0IsNodesetExpr()
064      {
065        return (null == m_arg0) ? true : m_arg0.isNodesetExpr();
066      }
067    
068      /**
069       * Execute the first argument expression that is expected to return a
070       * string.  If the argument is null, then get the string value from the
071       * current context node.
072       *
073       * @param xctxt Runtime XPath context.
074       *
075       * @return The string value of the first argument, or the string value of the
076       *         current context node if the first argument is null.
077       *
078       * @throws javax.xml.transform.TransformerException if an error occurs while
079       *                                   executing the argument expression.
080       */
081      protected XMLString getArg0AsString(XPathContext xctxt)
082              throws javax.xml.transform.TransformerException
083      {
084        if(null == m_arg0)
085        {
086          int currentNode = xctxt.getCurrentNode();
087          if(DTM.NULL == currentNode)
088            return XString.EMPTYSTRING;
089          else
090          {
091            DTM dtm = xctxt.getDTM(currentNode);
092            return dtm.getStringValue(currentNode);
093          }
094          
095        }
096        else
097          return m_arg0.execute(xctxt).xstr();   
098      }
099    
100      /**
101       * Execute the first argument expression that is expected to return a
102       * number.  If the argument is null, then get the number value from the
103       * current context node.
104       *
105       * @param xctxt Runtime XPath context.
106       *
107       * @return The number value of the first argument, or the number value of the
108       *         current context node if the first argument is null.
109       *
110       * @throws javax.xml.transform.TransformerException if an error occurs while
111       *                                   executing the argument expression.
112       */
113      protected double getArg0AsNumber(XPathContext xctxt)
114              throws javax.xml.transform.TransformerException
115      {
116    
117        if(null == m_arg0)
118        {
119          int currentNode = xctxt.getCurrentNode();
120          if(DTM.NULL == currentNode)
121            return 0;
122          else
123          {
124            DTM dtm = xctxt.getDTM(currentNode);
125            XMLString str = dtm.getStringValue(currentNode);
126            return str.toDouble();
127          }
128          
129        }
130        else
131          return m_arg0.execute(xctxt).num();
132      }
133    
134      /**
135       * Check that the number of arguments passed to this function is correct.
136       *
137       * @param argNum The number of arguments that is being passed to the function.
138       *
139       * @throws WrongNumberArgsException if the number of arguments is not 0 or 1.
140       */
141      public void checkNumberArgs(int argNum) throws WrongNumberArgsException
142      {
143        if (argNum > 1)
144          reportWrongNumberArgs();
145      }
146    
147      /**
148       * Constructs and throws a WrongNumberArgException with the appropriate
149       * message for this function object.
150       *
151       * @throws WrongNumberArgsException
152       */
153      protected void reportWrongNumberArgs() throws WrongNumberArgsException {
154          throw new WrongNumberArgsException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_ZERO_OR_ONE, null)); //"0 or 1");
155      }
156    
157      /**
158       * Tell if this expression or it's subexpressions can traverse outside
159       * the current subtree.
160       *
161       * @return true if traversal outside the context node's subtree can occur.
162       */
163      public boolean canTraverseOutsideSubtree()
164      {
165        return (null == m_arg0) ? false : super.canTraverseOutsideSubtree();
166      }
167    }