KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > style > UseWhenFilter


1 package net.sf.saxon.style;
2
3 import net.sf.saxon.Controller;
4 import net.sf.saxon.event.ProxyReceiver;
5 import net.sf.saxon.event.StartTagBuffer;
6 import net.sf.saxon.expr.*;
7 import net.sf.saxon.instruct.SlotManager;
8 import net.sf.saxon.om.NamespaceConstant;
9 import net.sf.saxon.trans.StaticError;
10 import net.sf.saxon.trans.XPathException;
11 import net.sf.saxon.type.ItemType;
12 import net.sf.saxon.type.Type;
13
14 import javax.xml.transform.Source JavaDoc;
15 import javax.xml.transform.TransformerException JavaDoc;
16 import javax.xml.transform.URIResolver JavaDoc;
17 import java.util.Stack JavaDoc;
18
19 /**
20  * This is a filter inserted into the input pipeline for processing stylesheet modules, whose
21  * task is to evaluate use-when expressions and discard those parts of the stylesheet module
22  * for which the use-when attribute evaluates to false.
23  */

24
25 public class UseWhenFilter extends ProxyReceiver {
26
27     private StartTagBuffer startTag;
28     private int useWhenCode;
29     private int xslUseWhenCode;
30     private int defaultNamespaceCode;
31     private int depthOfHole = 0;
32     private boolean emptyStylesheetElement = false;
33     private Stack JavaDoc defaultNamespaceStack = new Stack JavaDoc();
34
35     public UseWhenFilter(StartTagBuffer startTag) {
36         this.startTag = startTag;
37     }
38
39     /**
40      * Start of document
41      */

42
43     public void open() throws XPathException {
44         useWhenCode = getNamePool().allocate("", "", "use-when") & 0xfffff;
45         xslUseWhenCode = getNamePool().allocate("xsl", NamespaceConstant.XSLT, "use-when");
46         defaultNamespaceCode = getNamePool().allocate("", "", "xpath-default-namespace");
47         super.open();
48     }
49
50     /**
51      * Notify the start of an element.
52      *
53      * @param nameCode integer code identifying the name of the element within the name pool.
54      * @param typeCode integer code identifying the element's type within the name pool.
55      * @param properties bit-significant properties of the element node
56      */

57
58     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
59         defaultNamespaceStack.push(startTag.getAttribute(defaultNamespaceCode));
60         if (emptyStylesheetElement) {
61             depthOfHole = 1;
62         }
63         if (depthOfHole == 0) {
64             String JavaDoc useWhen;
65             if ((nameCode & 0xfffff) < 1024) {
66                 useWhen = startTag.getAttribute(useWhenCode);
67             } else {
68                 useWhen = startTag.getAttribute(xslUseWhenCode);
69             }
70             if (useWhen != null) {
71                 try {
72                     boolean b = evaluateUseWhen(useWhen, getDocumentLocator().getLineNumber(locationId));
73                     if (!b) {
74                         int fp = nameCode & 0xfffff;
75                         if (fp == StandardNames.XSL_STYLESHEET || fp == StandardNames.XSL_TRANSFORM) {
76                             emptyStylesheetElement = true;
77                         } else {
78                             depthOfHole = 1;
79                             return;
80                         }
81                     }
82                 } catch (XPathException e) {
83                     StaticError err = new StaticError("Error in use-when expression. " + e.getMessage());
84                     ExpressionLocation loc = new ExpressionLocation();
85                     loc.setSystemId(getDocumentLocator().getSystemId(locationId));
86                     loc.setLineNumber(getDocumentLocator().getLineNumber(locationId));
87                     err.setLocator(loc);
88                     err.setErrorCode(e.getErrorCodeLocalPart());
89                     try {
90                         getPipelineConfiguration().getErrorListener().fatalError(err);
91                     } catch (TransformerException JavaDoc tex) {
92                         throw StaticError.makeStaticError(tex);
93                     }
94                     throw err;
95                 }
96             }
97         } else {
98             depthOfHole++;
99         }
100         super.startElement(nameCode, typeCode, locationId, properties);
101     }
102
103     /**
104      * Notify a namespace. Namespaces are notified <b>after</b> the startElement event, and before
105      * any children for the element. The namespaces that are reported are only required
106      * to include those that are different from the parent element; however, duplicates may be reported.
107      * A namespace must not conflict with any namespaces already used for element or attribute names.
108      *
109      * @param namespaceCode an integer: the top half is a prefix code, the bottom half a URI code.
110      * These may be translated into an actual prefix and URI using the name pool. A prefix code of
111      * zero represents the empty prefix (that is, the default namespace). A URI code of zero represents
112      * a URI of "", that is, a namespace undeclaration.
113      * @throws IllegalStateException: attempt to output a namespace when there is no open element
114      * start tag
115      */

116
117     public void namespace(int namespaceCode, int properties) throws XPathException {
118         if (depthOfHole == 0) {
119             super.namespace(namespaceCode, properties);
120         }
121     }
122
123     /**
124      * Notify an attribute. Attributes are notified after the startElement event, and before any
125      * children. Namespaces and attributes may be intermingled.
126      *
127      * @param nameCode The name of the attribute, as held in the name pool
128      * @param typeCode The type of the attribute, as held in the name pool
129      * @param properties Bit significant value. The following bits are defined:
130      * <dd>DISABLE_ESCAPING</dd> <dt>Disable escaping for this attribute</dt>
131      * <dd>NO_SPECIAL_CHARACTERS</dd> <dt>Attribute value contains no special characters</dt>
132      * @throws IllegalStateException: attempt to output an attribute when there is no open element
133      * start tag
134      */

135
136     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties) throws XPathException {
137         if (depthOfHole == 0) {
138             super.attribute(nameCode, typeCode, value, locationId, properties);
139         }
140     }
141
142     /**
143      * Notify the start of the content, that is, the completion of all attributes and namespaces.
144      * Note that the initial receiver of output from XSLT instructions will not receive this event,
145      * it has to detect it itself. Note that this event is reported for every element even if it has
146      * no attributes, no namespaces, and no content.
147      */

148
149
150     public void startContent() throws XPathException {
151         if (depthOfHole == 0) {
152             super.startContent();
153         }
154     }
155
156     /**
157      * End of element
158      */

159
160     public void endElement() throws XPathException {
161         defaultNamespaceStack.pop();
162         if (depthOfHole > 0) {
163             depthOfHole--;
164         } else {
165             super.endElement();
166         }
167     }
168
169     /**
170      * Character data
171      */

172
173     public void characters(CharSequence JavaDoc chars, int locationId, int properties) throws XPathException {
174         if (depthOfHole == 0) {
175             super.characters(chars, locationId, properties);
176         }
177     }
178
179     /**
180      * Processing Instruction
181      */

182
183     public void processingInstruction(String JavaDoc target, CharSequence JavaDoc data, int locationId, int properties) {
184         // these are ignored in a stylesheet
185
}
186
187     /**
188      * Output a comment
189      */

190
191     public void comment(CharSequence JavaDoc chars, int locationId, int properties) throws XPathException {
192         // these are ignored in a stylesheet
193
}
194
195     /**
196      * Evaluate a use-when attribute
197      */

198
199     public boolean evaluateUseWhen(String JavaDoc expression, int locationId) throws XPathException {
200         UseWhenStaticContext staticContext = new UseWhenStaticContext(getConfiguration(), startTag);
201         // The following is an approximation: it doesn't take account of xml:base attributes
202
staticContext.setBaseURI(getDocumentLocator().getSystemId(locationId));
203         for (int i=defaultNamespaceStack.size()-1; i>=0; i--) {
204             String JavaDoc uri = (String JavaDoc)defaultNamespaceStack.get(i);
205             if (uri != null) {
206                 short code = getNamePool().getCodeForURI(uri);
207                 staticContext.setDefaultElementNamespace(code);
208                 break;
209             }
210         }
211         Expression expr = ExpressionTool.make(expression, staticContext,
212                 0, Token.EOF, getDocumentLocator().getLineNumber(locationId));
213         ItemType contextItemType = Type.ITEM_TYPE;
214         expr = expr.typeCheck(staticContext, contextItemType);
215         SlotManager stackFrameMap = getPipelineConfiguration().getConfiguration().makeSlotManager();
216         ExpressionTool.allocateSlots(expr, stackFrameMap.getNumberOfVariables(), stackFrameMap);
217         Controller controller = new Controller(getConfiguration());
218         controller.setURIResolver(new URIPreventer());
219         XPathContext dynamicContext = controller.newXPathContext();
220         dynamicContext = dynamicContext.newCleanContext();
221         ((XPathContextMajor)dynamicContext).openStackFrame(stackFrameMap.getNumberOfVariables());
222         return ExpressionTool.effectiveBooleanValue(expr.iterate(dynamicContext));
223     }
224
225     /**
226      * Define a URIResolver that disallows all URIs
227      */

228
229     private static class URIPreventer implements URIResolver JavaDoc {
230         /**
231          * Called by the processor when it encounters
232          * an xsl:include, xsl:import, or document() function.
233          *
234          * @param href An href attribute, which may be relative or absolute.
235          * @param base The base URI against which the first argument will be made
236          * absolute if the absolute URI is required.
237          * @return A Source object, or null if the href cannot be resolved,
238          * and the processor should try to resolve the URI itself.
239          * @throws javax.xml.transform.TransformerException
240          * if an error occurs when trying to
241          * resolve the URI.
242          */

243         public Source JavaDoc resolve(String JavaDoc href, String JavaDoc base) throws TransformerException JavaDoc {
244             throw new TransformerException JavaDoc("No external documents are available within an [xsl]use-when expression");
245         }
246     }
247
248
249 }
250
251 //
252
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
253
// you may not use this file except in compliance with the License. You may obtain a copy of the
254
// License at http://www.mozilla.org/MPL/
255
//
256
// Software distributed under the License is distributed on an "AS IS" basis,
257
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
258
// See the License for the specific language governing rights and limitations under the License.
259
//
260
// The Original Code is: all this file.
261
//
262
// The Initial Developer of the Original Code is Michael H. Kay.
263
//
264
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
265
//
266
// Contributor(s): none.
267
//
268

269
Popular Tags