001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.ExpressionTool;
005: import net.sf.saxon.expr.StaticContext;
006: import net.sf.saxon.expr.XPathContext;
007: import net.sf.saxon.instruct.InstructionDetails;
008: import net.sf.saxon.om.*;
009: import net.sf.saxon.trace.Location;
010: import net.sf.saxon.trace.TraceListener;
011: import net.sf.saxon.trans.XPathException;
012: import net.sf.saxon.type.Type;
013: import net.sf.saxon.value.Value;
014:
015: /**
016: * This class supports the XPath 2.0 function trace().
017: * The value is traced to the System.err stream, unless a TraceListener is in use,
018: * in which case the information is sent to the TraceListener
019: */
020:
021: public class Trace extends SystemFunction {
022:
023: NamespaceResolver resolver;
024:
025: // This is retained so that the static namespace context is available if required by the TraceListener
026:
027: /**
028: * Simplify the function call. This implementation saves the static namespace context, in case it is
029: * needed by the TraceListener.
030: */
031:
032: public Expression simplify(StaticContext env) throws XPathException {
033: resolver = env.getNamespaceResolver();
034: return super .simplify(env);
035: }
036:
037: /**
038: * preEvaluate: this method suppresses compile-time evaluation by doing nothing
039: */
040:
041: public Expression preEvaluate(StaticContext env) {
042: return this ;
043: }
044:
045: /**
046: * Get the static properties of this expression (other than its type). The result is
047: * bit-significant. These properties are used for optimizations. In general, if
048: * property bit is set, it is true, but if it is unset, the value is unknown.
049: */
050:
051: public int computeSpecialProperties() {
052: return argument[0].getSpecialProperties();
053: }
054:
055: /**
056: * Get the static cardinality
057: */
058:
059: public int computeCardinality() {
060: return argument[0].getCardinality();
061: }
062:
063: /**
064: * Evaluate the function
065: */
066:
067: public Item evaluateItem(XPathContext context)
068: throws XPathException {
069: Item val = argument[0].evaluateItem(context);
070: String label = argument[1].evaluateAsString(context);
071: if (context.getController().isTracing()) {
072: notifyListener(label, Value.asValue(val), context);
073: } else {
074: traceItem(val, label);
075: }
076: return val;
077: }
078:
079: private void notifyListener(String label, Value val,
080: XPathContext context) {
081: InstructionDetails info = (InstructionDetails) getInstructionInfo();
082: info.setConstructType(Location.TRACE_CALL);
083: info.setNamespaceResolver(resolver);
084: info.setProperty("label", label);
085: info.setProperty("value", val);
086: TraceListener listener = context.getController()
087: .getTraceListener();
088: listener.enter(info, context);
089: listener.leave(info);
090: }
091:
092: private void traceItem(Item val, String label) {
093: if (val == null) {
094: System.err.println(label + ": empty sequence");
095: } else {
096: if (val instanceof NodeInfo) {
097: System.err.println(label + ": "
098: + Type.displayTypeName(val) + ": "
099: + Navigator.getPath((NodeInfo) val));
100: } else {
101: System.err.println(label + ": "
102: + Type.displayTypeName(val) + ": "
103: + val.getStringValue());
104: }
105: }
106: }
107:
108: /**
109: * Iterate over the results of the function
110: */
111:
112: public SequenceIterator iterate(XPathContext context)
113: throws XPathException {
114: if (context.getController().isTracing()) {
115: String label = argument[1].evaluateAsString(context);
116: Value value = ExpressionTool.eagerEvaluate(argument[0],
117: context);
118: notifyListener(label, value, context);
119: return value.iterate(context);
120: } else {
121: return new TracingIterator(argument[0].iterate(context),
122: argument[1].evaluateAsString(context));
123: }
124: }
125:
126: /**
127: * Tracing Iterator class
128: */
129:
130: public class TracingIterator implements SequenceIterator {
131:
132: SequenceIterator base;
133: String label;
134: boolean empty = true;
135:
136: public TracingIterator(SequenceIterator base, String label) {
137: this .base = base;
138: this .label = label;
139: }
140:
141: public Item next() throws XPathException {
142: Item n = base.next();
143: if (n == null) {
144: if (empty) {
145: traceItem(null, label);
146: }
147: } else {
148: traceItem(n, label + " [" + position() + ']');
149: empty = false;
150: }
151: return n;
152: }
153:
154: public Item current() {
155: return base.current();
156: }
157:
158: public int position() {
159: return base.position();
160: }
161:
162: public SequenceIterator getAnother() throws XPathException {
163: return new TracingIterator(base.getAnother(), label);
164: }
165:
166: /**
167: * Get properties of this iterator, as a bit-significant integer.
168: *
169: * @return the properties of this iterator. This will be some combination of
170: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
171: * and {@link LOOKAHEAD}. It is always
172: * acceptable to return the value zero, indicating that there are no known special properties.
173: * It is acceptable for the properties of the iterator to change depending on its state.
174: */
175:
176: public int getProperties() {
177: return 0;
178: }
179: }
180:
181: }
182:
183: //
184: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
185: // you may not use this file except in compliance with the License. You may obtain a copy of the
186: // License at http://www.mozilla.org/MPL/
187: //
188: // Software distributed under the License is distributed on an "AS IS" basis,
189: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
190: // See the License for the specific language governing rights and limitations under the License.
191: //
192: // The Original Code is: all this file.
193: //
194: // The Initial Developer of the Original Code is Michael H. Kay.
195: //
196: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
197: //
198: // Contributor(s): none.
199: //
|