001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: FuncId.java,v 1.15 2004/08/17 19:25:36 jycli Exp $
018: */
019: package org.apache.xpath.functions;
020:
021: import java.util.StringTokenizer;
022:
023: import org.apache.xml.dtm.DTM;
024: import org.apache.xml.dtm.DTMIterator;
025: import org.apache.xml.utils.StringVector;
026: import org.apache.xpath.NodeSetDTM;
027: import org.apache.xpath.XPathContext;
028: import org.apache.xpath.objects.XNodeSet;
029: import org.apache.xpath.objects.XObject;
030: import org.apache.xpath.res.XPATHErrorResources;
031:
032: /**
033: * Execute the Id() function.
034: * @xsl.usage advanced
035: */
036: public class FuncId extends FunctionOneArg {
037: static final long serialVersionUID = 8930573966143567310L;
038:
039: /**
040: * Fill in a list with nodes that match a space delimited list if ID
041: * ID references.
042: *
043: * @param xctxt The runtime XPath context.
044: * @param docContext The document where the nodes are being looked for.
045: * @param refval A space delimited list of ID references.
046: * @param usedrefs List of references for which nodes were found.
047: * @param nodeSet Node set where the nodes will be added to.
048: * @param mayBeMore true if there is another set of nodes to be looked for.
049: *
050: * @return The usedrefs value.
051: */
052: private StringVector getNodesByID(XPathContext xctxt,
053: int docContext, String refval, StringVector usedrefs,
054: NodeSetDTM nodeSet, boolean mayBeMore) {
055:
056: if (null != refval) {
057: String ref = null;
058: // DOMHelper dh = xctxt.getDOMHelper();
059: StringTokenizer tokenizer = new StringTokenizer(refval);
060: boolean hasMore = tokenizer.hasMoreTokens();
061: DTM dtm = xctxt.getDTM(docContext);
062:
063: while (hasMore) {
064: ref = tokenizer.nextToken();
065: hasMore = tokenizer.hasMoreTokens();
066:
067: if ((null != usedrefs) && usedrefs.contains(ref)) {
068: ref = null;
069:
070: continue;
071: }
072:
073: int node = dtm.getElementById(ref);
074:
075: if (DTM.NULL != node)
076: nodeSet.addNodeInDocOrder(node, xctxt);
077:
078: if ((null != ref) && (hasMore || mayBeMore)) {
079: if (null == usedrefs)
080: usedrefs = new StringVector();
081:
082: usedrefs.addElement(ref);
083: }
084: }
085: }
086:
087: return usedrefs;
088: }
089:
090: /**
091: * Execute the function. The function must return
092: * a valid object.
093: * @param xctxt The current execution context.
094: * @return A valid XObject.
095: *
096: * @throws javax.xml.transform.TransformerException
097: */
098: public XObject execute(XPathContext xctxt)
099: throws javax.xml.transform.TransformerException {
100:
101: int context = xctxt.getCurrentNode();
102: DTM dtm = xctxt.getDTM(context);
103: int docContext = dtm.getDocument();
104:
105: if (DTM.NULL == docContext)
106: error(xctxt,
107: XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC,
108: null);
109:
110: XObject arg = m_arg0.execute(xctxt);
111: int argType = arg.getType();
112: XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
113: NodeSetDTM nodeSet = nodes.mutableNodeset();
114:
115: if (XObject.CLASS_NODESET == argType) {
116: DTMIterator ni = arg.iter();
117: StringVector usedrefs = null;
118: int pos = ni.nextNode();
119:
120: while (DTM.NULL != pos) {
121: DTM ndtm = ni.getDTM(pos);
122: String refval = ndtm.getStringValue(pos).toString();
123:
124: pos = ni.nextNode();
125: usedrefs = getNodesByID(xctxt, docContext, refval,
126: usedrefs, nodeSet, DTM.NULL != pos);
127: }
128: // ni.detach();
129: } else if (XObject.CLASS_NULL == argType) {
130: return nodes;
131: } else {
132: String refval = arg.str();
133:
134: getNodesByID(xctxt, docContext, refval, null, nodeSet,
135: false);
136: }
137:
138: return nodes;
139: }
140: }
|