Home | History | Annotate | Download | only in functions
      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: FuncId.java 468655 2006-10-28 07:12:06Z minchau $
     20  */
     21 package org.apache.xpath.functions;
     22 
     23 import java.util.StringTokenizer;
     24 
     25 import org.apache.xml.dtm.DTM;
     26 import org.apache.xml.dtm.DTMIterator;
     27 import org.apache.xml.utils.StringVector;
     28 import org.apache.xpath.NodeSetDTM;
     29 import org.apache.xpath.XPathContext;
     30 import org.apache.xpath.objects.XNodeSet;
     31 import org.apache.xpath.objects.XObject;
     32 import org.apache.xpath.res.XPATHErrorResources;
     33 
     34 /**
     35  * Execute the Id() function.
     36  * @xsl.usage advanced
     37  */
     38 public class FuncId extends FunctionOneArg
     39 {
     40     static final long serialVersionUID = 8930573966143567310L;
     41 
     42   /**
     43    * Fill in a list with nodes that match a space delimited list if ID
     44    * ID references.
     45    *
     46    * @param xctxt The runtime XPath context.
     47    * @param docContext The document where the nodes are being looked for.
     48    * @param refval A space delimited list of ID references.
     49    * @param usedrefs List of references for which nodes were found.
     50    * @param nodeSet Node set where the nodes will be added to.
     51    * @param mayBeMore true if there is another set of nodes to be looked for.
     52    *
     53    * @return The usedrefs value.
     54    */
     55   private StringVector getNodesByID(XPathContext xctxt, int docContext,
     56                                     String refval, StringVector usedrefs,
     57                                     NodeSetDTM nodeSet, boolean mayBeMore)
     58   {
     59 
     60     if (null != refval)
     61     {
     62       String ref = null;
     63 //      DOMHelper dh = xctxt.getDOMHelper();
     64       StringTokenizer tokenizer = new StringTokenizer(refval);
     65       boolean hasMore = tokenizer.hasMoreTokens();
     66       DTM dtm = xctxt.getDTM(docContext);
     67 
     68       while (hasMore)
     69       {
     70         ref = tokenizer.nextToken();
     71         hasMore = tokenizer.hasMoreTokens();
     72 
     73         if ((null != usedrefs) && usedrefs.contains(ref))
     74         {
     75           ref = null;
     76 
     77           continue;
     78         }
     79 
     80         int node = dtm.getElementById(ref);
     81 
     82         if (DTM.NULL != node)
     83           nodeSet.addNodeInDocOrder(node, xctxt);
     84 
     85         if ((null != ref) && (hasMore || mayBeMore))
     86         {
     87           if (null == usedrefs)
     88             usedrefs = new StringVector();
     89 
     90           usedrefs.addElement(ref);
     91         }
     92       }
     93     }
     94 
     95     return usedrefs;
     96   }
     97 
     98   /**
     99    * Execute the function.  The function must return
    100    * a valid object.
    101    * @param xctxt The current execution context.
    102    * @return A valid XObject.
    103    *
    104    * @throws javax.xml.transform.TransformerException
    105    */
    106   public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
    107   {
    108 
    109     int context = xctxt.getCurrentNode();
    110     DTM dtm = xctxt.getDTM(context);
    111     int docContext = dtm.getDocument();
    112 
    113     if (DTM.NULL == docContext)
    114       error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
    115 
    116     XObject arg = m_arg0.execute(xctxt);
    117     int argType = arg.getType();
    118     XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
    119     NodeSetDTM nodeSet = nodes.mutableNodeset();
    120 
    121     if (XObject.CLASS_NODESET == argType)
    122     {
    123       DTMIterator ni = arg.iter();
    124       StringVector usedrefs = null;
    125       int pos = ni.nextNode();
    126 
    127       while (DTM.NULL != pos)
    128       {
    129         DTM ndtm = ni.getDTM(pos);
    130         String refval = ndtm.getStringValue(pos).toString();
    131 
    132         pos = ni.nextNode();
    133         usedrefs = getNodesByID(xctxt, docContext, refval, usedrefs, nodeSet,
    134                                 DTM.NULL != pos);
    135       }
    136       // ni.detach();
    137     }
    138     else if (XObject.CLASS_NULL == argType)
    139     {
    140       return nodes;
    141     }
    142     else
    143     {
    144       String refval = arg.str();
    145 
    146       getNodesByID(xctxt, docContext, refval, null, nodeSet, false);
    147     }
    148 
    149     return nodes;
    150   }
    151 }
    152