01: /*
02: * Copyright 1999-2004 The Apache Software Foundation.
03: *
04: * Licensed under the Apache License, Version 2.0 (the "License");
05: * you may not use this file except in compliance with the License.
06: * You may obtain a copy of the License at
07: *
08: * http://www.apache.org/licenses/LICENSE-2.0
09: *
10: * Unless required by applicable law or agreed to in writing, software
11: * distributed under the License is distributed on an "AS IS" BASIS,
12: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13: * See the License for the specific language governing permissions and
14: * limitations under the License.
15: */
16: /*
17: * $Id: VariableSafeAbsRef.java,v 1.6 2004/08/17 19:25:41 jycli Exp $
18: */
19: package org.apache.xpath.operations;
20:
21: import org.apache.xml.dtm.DTMManager;
22: import org.apache.xpath.Expression;
23: import org.apache.xpath.XPathContext;
24: import org.apache.xpath.objects.XNodeSet;
25: import org.apache.xpath.objects.XObject;
26:
27: /**
28: * This is a "smart" variable reference that is used in situations where
29: * an absolute path is optimized into a variable reference, but may
30: * be used in some situations where the document context may have changed.
31: * For instance, in select="document(doc/@href)//name[//salary > 7250]", the
32: * root in the predicate will be different for each node in the set. While
33: * this is easy to detect statically in this case, in other cases static
34: * detection would be very hard or impossible. So, this class does a dynamic check
35: * to make sure the document context of the referenced variable is the same as
36: * the current document context, and, if it is not, execute the referenced variable's
37: * expression with the current context instead.
38: */
39: public class VariableSafeAbsRef extends Variable {
40: static final long serialVersionUID = -9174661990819967452L;
41:
42: /**
43: * Dereference the variable, and return the reference value. Note that lazy
44: * evaluation will occur. If a variable within scope is not found, a warning
45: * will be sent to the error listener, and an empty nodeset will be returned.
46: *
47: *
48: * @param xctxt The runtime execution context.
49: *
50: * @return The evaluated variable, or an empty nodeset if not found.
51: *
52: * @throws javax.xml.transform.TransformerException
53: */
54: public XObject execute(XPathContext xctxt, boolean destructiveOK)
55: throws javax.xml.transform.TransformerException {
56: XNodeSet xns = (XNodeSet) super .execute(xctxt, destructiveOK);
57: DTMManager dtmMgr = xctxt.getDTMManager();
58: int context = xctxt.getContextNode();
59: if (dtmMgr.getDTM(xns.getRoot()).getDocument() != dtmMgr
60: .getDTM(context).getDocument()) {
61: Expression expr = (Expression) xns.getContainedIter();
62: xns = (XNodeSet) expr.asIterator(xctxt, context);
63: }
64: return xns;
65: }
66:
67: }
|