1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xpath.internal.functions; 23 24import java.util.StringTokenizer; 25 26import com.sun.org.apache.xml.internal.dtm.DTM; 27import com.sun.org.apache.xml.internal.dtm.DTMIterator; 28import com.sun.org.apache.xml.internal.utils.StringVector; 29import com.sun.org.apache.xpath.internal.NodeSetDTM; 30import com.sun.org.apache.xpath.internal.XPathContext; 31import com.sun.org.apache.xpath.internal.objects.XNodeSet; 32import com.sun.org.apache.xpath.internal.objects.XObject; 33import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; 34 35/** 36 * Execute the Id() function. 37 * @xsl.usage advanced 38 */ 39public class FuncId extends FunctionOneArg 40{ 41 static final long serialVersionUID = 8930573966143567310L; 42 43 /** 44 * Fill in a list with nodes that match a space delimited list if ID 45 * ID references. 46 * 47 * @param xctxt The runtime XPath context. 48 * @param docContext The document where the nodes are being looked for. 49 * @param refval A space delimited list of ID references. 50 * @param usedrefs List of references for which nodes were found. 51 * @param nodeSet Node set where the nodes will be added to. 52 * @param mayBeMore true if there is another set of nodes to be looked for. 53 * 54 * @return The usedrefs value. 55 */ 56 private StringVector getNodesByID(XPathContext xctxt, int docContext, 57 String refval, StringVector usedrefs, 58 NodeSetDTM nodeSet, boolean mayBeMore) 59 { 60 61 if (null != refval) 62 { 63 String ref = null; 64// DOMHelper dh = xctxt.getDOMHelper(); 65 StringTokenizer tokenizer = new StringTokenizer(refval); 66 boolean hasMore = tokenizer.hasMoreTokens(); 67 DTM dtm = xctxt.getDTM(docContext); 68 69 while (hasMore) 70 { 71 ref = tokenizer.nextToken(); 72 hasMore = tokenizer.hasMoreTokens(); 73 74 if ((null != usedrefs) && usedrefs.contains(ref)) 75 { 76 ref = null; 77 78 continue; 79 } 80 81 int node = dtm.getElementById(ref); 82 83 if (DTM.NULL != node) 84 nodeSet.addNodeInDocOrder(node, xctxt); 85 86 if ((null != ref) && (hasMore || mayBeMore)) 87 { 88 if (null == usedrefs) 89 usedrefs = new StringVector(); 90 91 usedrefs.addElement(ref); 92 } 93 } 94 } 95 96 return usedrefs; 97 } 98 99 /** 100 * Execute the function. The function must return 101 * a valid object. 102 * @param xctxt The current execution context. 103 * @return A valid XObject. 104 * 105 * @throws javax.xml.transform.TransformerException 106 */ 107 public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException 108 { 109 110 int context = xctxt.getCurrentNode(); 111 DTM dtm = xctxt.getDTM(context); 112 int docContext = dtm.getDocument(); 113 114 if (DTM.NULL == docContext) 115 error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null); 116 117 XObject arg = m_arg0.execute(xctxt); 118 int argType = arg.getType(); 119 XNodeSet nodes = new XNodeSet(xctxt.getDTMManager()); 120 NodeSetDTM nodeSet = nodes.mutableNodeset(); 121 122 if (XObject.CLASS_NODESET == argType) 123 { 124 DTMIterator ni = arg.iter(); 125 StringVector usedrefs = null; 126 int pos = ni.nextNode(); 127 128 while (DTM.NULL != pos) 129 { 130 DTM ndtm = ni.getDTM(pos); 131 String refval = ndtm.getStringValue(pos).toString(); 132 133 pos = ni.nextNode(); 134 usedrefs = getNodesByID(xctxt, docContext, refval, usedrefs, nodeSet, 135 DTM.NULL != pos); 136 } 137 // ni.detach(); 138 } 139 else if (XObject.CLASS_NULL == argType) 140 { 141 return nodes; 142 } 143 else 144 { 145 String refval = arg.str(); 146 147 getNodesByID(xctxt, docContext, refval, null, nodeSet, false); 148 } 149 150 return nodes; 151 } 152} 153