19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: FuncId.java 468655 2006-10-28 07:12:06Z minchau $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xpath.functions;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.StringTokenizer;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTM;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.dtm.DTMIterator;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.utils.StringVector;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.NodeSetDTM;
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.XPathContext;
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XNodeSet;
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XObject;
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.res.XPATHErrorResources;
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Execute the Id() function.
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage advanced
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class FuncId extends FunctionOneArg
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    static final long serialVersionUID = 8930573966143567310L;
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Fill in a list with nodes that match a space delimited list if ID
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * ID references.
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The runtime XPath context.
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param docContext The document where the nodes are being looked for.
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param refval A space delimited list of ID references.
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param usedrefs List of references for which nodes were found.
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param nodeSet Node set where the nodes will be added to.
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param mayBeMore true if there is another set of nodes to be looked for.
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The usedrefs value.
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private StringVector getNodesByID(XPathContext xctxt, int docContext,
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                    String refval, StringVector usedrefs,
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                    NodeSetDTM nodeSet, boolean mayBeMore)
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (null != refval)
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String ref = null;
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson//      DOMHelper dh = xctxt.getDOMHelper();
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      StringTokenizer tokenizer = new StringTokenizer(refval);
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      boolean hasMore = tokenizer.hasMoreTokens();
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DTM dtm = xctxt.getDTM(docContext);
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (hasMore)
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        ref = tokenizer.nextToken();
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        hasMore = tokenizer.hasMoreTokens();
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if ((null != usedrefs) && usedrefs.contains(ref))
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          ref = null;
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          continue;
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int node = dtm.getElementById(ref);
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if (DTM.NULL != node)
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          nodeSet.addNodeInDocOrder(node, xctxt);
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        if ((null != ref) && (hasMore || mayBeMore))
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (null == usedrefs)
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            usedrefs = new StringVector();
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          usedrefs.addElement(ref);
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return usedrefs;
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Execute the function.  The function must return
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * a valid object.
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The current execution context.
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return A valid XObject.
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int context = xctxt.getCurrentNode();
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    DTM dtm = xctxt.getDTM(context);
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int docContext = dtm.getDocument();
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (DTM.NULL == docContext)
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject arg = m_arg0.execute(xctxt);
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int argType = arg.getType();
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    NodeSetDTM nodeSet = nodes.mutableNodeset();
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (XObject.CLASS_NODESET == argType)
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      DTMIterator ni = arg.iter();
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      StringVector usedrefs = null;
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int pos = ni.nextNode();
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      while (DTM.NULL != pos)
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        DTM ndtm = ni.getDTM(pos);
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        String refval = ndtm.getStringValue(pos).toString();
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        pos = ni.nextNode();
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        usedrefs = getNodesByID(xctxt, docContext, refval, usedrefs, nodeSet,
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                DTM.NULL != pos);
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // ni.detach();
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (XObject.CLASS_NULL == argType)
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return nodes;
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      String refval = arg.str();
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      getNodesByID(xctxt, docContext, refval, null, nodeSet, false);
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return nodes;
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
152