KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > style > StyleNodeFactory


1 package com.icl.saxon.style;
2 import com.icl.saxon.tree.AttributeCollection;
3 import com.icl.saxon.*;
4 import com.icl.saxon.om.*;
5 import com.icl.saxon.tree.*;
6
7 import javax.xml.transform.*;
8 import org.xml.sax.Locator JavaDoc;
9 import org.xml.sax.SAXException JavaDoc;
10 import java.util.*;
11
12 /**
13   * Class StyleNodeFactory. <br>
14   * A Factory for nodes in the stylesheet tree. <br>
15   * Currently only allows Element nodes to be user-constructed.
16   * @author <A HREF="mailto:mhkay@iclway.co.uk>Michael H. Kay</A>
17   */

18
19 public class StyleNodeFactory implements NodeFactory {
20
21     Hashtable userStyles = new Hashtable();
22     NamePool namePool;
23     StandardNames sn;
24
25     public StyleNodeFactory(NamePool pool) {
26         
27         namePool = pool;
28         sn = pool.getStandardNames();
29     }
30     
31     public StandardNames getStandardNames() {
32         return namePool.getStandardNames();
33     }
34     
35     /**
36     * Create an Element node. Note, if there is an error detected while constructing
37     * the Element, we add the element anyway, and return success, but flag the element
38     * with a validation error. In principle this should allow us to report more than
39     * one error from a single compilation.
40     * @param tag The element name
41     * @param attlist the attribute list
42     */

43
44     public ElementImpl makeElementNode(
45                         NodeInfo parent,
46                         int nameCode,
47                         AttributeCollection attlist,
48                         int[] namespaces,
49                         int namespacesUsed,
50                         Locator JavaDoc locator,
51                         int sequence)
52     {
53         // System.err.println("Make element node " + nameCode);
54
boolean toplevel = (parent instanceof XSLStyleSheet);
55
56         String JavaDoc baseURI = null;
57         int lineNumber = -1;
58
59         if (locator!=null) {
60             baseURI = locator.getSystemId();
61             lineNumber = locator.getLineNumber();
62         }
63
64         int f = nameCode&0xfffff;
65         StyleElement e = makeXSLElement(f);
66
67         if (e != null) {
68             try {
69                 e.setNamespaceDeclarations(namespaces, namespacesUsed);
70                 e.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequence);
71                 if (e instanceof XSLStyleSheet) {
72                     e.processExtensionElementAttribute(sn.EXTENSION_ELEMENT_PREFIXES);
73                     e.processExcludedNamespaces(sn.EXCLUDE_RESULT_PREFIXES);
74                     e.processVersionAttribute(sn.VERSION);
75                 }
76             } catch (TransformerException err) {
77                 e.setValidationError(err, StyleElement.REPORT_ALWAYS);
78             }
79             return e;
80             
81         } else {
82
83             short uriCode = namePool.getURICode(nameCode);
84             String JavaDoc localname = namePool.getLocalName(nameCode);
85
86             Class JavaDoc assumedClass = LiteralResultElement.class;
87     
88             // We can't work out the final class of the node until we've examined its attributes
89
// such as version and extension-element-prefixes; but we can have a good guess, and
90
// change it later if need be.
91

92             StyleElement temp = null;
93             boolean assumedSaxonElement = false;
94             
95             // map EXSLT func:function and func:result onto Saxon equivalents
96

97             if (uriCode == Namespace.EXSLT_FUNCTIONS_CODE) {
98                 temp = makeExsltFunctionsElement(f);
99                 if (temp!=null) {
100                     assumedClass = temp.getClass();
101                     assumedSaxonElement = true;
102                 }
103             
104             } else if (uriCode == Namespace.SAXON_CODE) {
105                 temp = makeSaxonElement(f);
106                 if (temp!=null) {
107                     assumedClass = temp.getClass();
108                     assumedSaxonElement = true;
109                 }
110             }
111             if (temp==null) {
112                 temp = new LiteralResultElement();
113             }
114
115             temp.setNamespaceDeclarations(namespaces, namespacesUsed);
116     
117             try {
118                 temp.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequence);
119                 temp.processExtensionElementAttribute(sn.XSL_EXTENSION_ELEMENT_PREFIXES);
120                 temp.processExcludedNamespaces(sn.XSL_EXCLUDE_RESULT_PREFIXES);
121                 temp.processVersionAttribute(sn.XSL_VERSION);
122             } catch (TransformerException err) {
123                 temp.setValidationError(err, StyleElement.REPORT_UNLESS_FORWARDS_COMPATIBLE);
124             }
125             
126             // Now we work out what class of element we really wanted, and change it if necessary
127

128             TransformerException reason = null;
129             Class JavaDoc actualClass = LiteralResultElement.class;
130     
131             if (uriCode == Namespace.XSLT_CODE) {
132                 reason = new TransformerConfigurationException("Unknown XSLT element: " + localname);
133                 actualClass = AbsentExtensionElement.class;
134                 temp.setValidationError(reason, StyleElement.REPORT_UNLESS_FORWARDS_COMPATIBLE);
135             } else if (uriCode == Namespace.SAXON_CODE || uriCode == Namespace.EXSLT_FUNCTIONS_CODE) {
136                 if (toplevel || temp.isExtensionNamespace(uriCode)) {
137                     if (assumedSaxonElement) {
138                         // all is well
139
actualClass = assumedClass;
140                     } else {
141                         actualClass = AbsentExtensionElement.class;
142                         reason = new TransformerConfigurationException(
143                                         "Unknown Saxon extension element: " + localname);
144                         temp.setValidationError(reason, StyleElement.REPORT_IF_INSTANTIATED);
145                     }
146                 } else {
147                     actualClass = LiteralResultElement.class;
148                 }
149             } else if (temp.isExtensionNamespace(uriCode) && !toplevel) {
150                 Integer JavaDoc nameKey = new Integer JavaDoc(nameCode&0xfffff);
151
152                 actualClass = (Class JavaDoc)userStyles.get(nameKey);
153                 if (actualClass==null) {
154                      ExtensionElementFactory factory = getFactory(uriCode);
155                      if (factory != null) {
156                         actualClass = factory.getExtensionClass(localname);
157                         if (actualClass != null) {
158                             userStyles.put(nameKey, actualClass); // for quicker access next time
159
}
160                      }
161                      if (actualClass == null) {
162                         
163                         // if we can't instantiate an extension element, we don't give up
164
// immediately, because there might be an xsl:fallback defined. We
165
// create a surrogate element called AbsentExtensionElement, and
166
// save the reason for failure just in case there is no xsl:fallback
167

168                         actualClass = AbsentExtensionElement.class;
169                         reason = new TransformerConfigurationException("Unknown extension element");
170                         temp.setValidationError(reason, StyleElement.REPORT_IF_INSTANTIATED);
171                     }
172                 }
173             } else {
174                 actualClass = LiteralResultElement.class;
175             }
176             
177             StyleElement node;
178             if (!actualClass.equals(assumedClass)) {
179                 try {
180                     node = (StyleElement)actualClass.newInstance();
181                     //if (reason!=null) {
182
// node.setValidationError(reason);
183
//}
184
} catch (java.lang.InstantiationException JavaDoc err1) {
185                     throw new TransformerFactoryConfigurationError(err1, "Failed to create instance of " + actualClass.getName());
186                 } catch (java.lang.IllegalAccessException JavaDoc err2) {
187                     throw new TransformerFactoryConfigurationError(err2, "Failed to access class " + actualClass.getName());
188                 }
189                 node.substituteFor(temp); // replace temporary node with the new one
190
} else {
191                 node = temp; // the original element will do the job
192
}
193             return node;
194         }
195     }
196
197     /**
198     * Make an XSL element node
199     */

200     
201     private StyleElement makeXSLElement(int f) {
202
203         StyleElement e = null;
204
205         if (f==sn.XSL_APPLY_IMPORTS) e=new XSLApplyImports();
206         else if (f==sn.XSL_APPLY_TEMPLATES) e=new XSLApplyTemplates();
207         else if (f==sn.XSL_ATTRIBUTE) e=new XSLAttribute();
208         else if (f==sn.XSL_ATTRIBUTE_SET) e=new XSLAttributeSet();
209         else if (f==sn.XSL_CALL_TEMPLATE) e=new XSLCallTemplate();
210         else if (f==sn.XSL_CHOOSE) e=new XSLChoose();
211         else if (f==sn.XSL_COMMENT) e=new XSLComment();
212         else if (f==sn.XSL_COPY) e=new XSLCopy();
213         else if (f==sn.XSL_COPY_OF) e=new XSLCopyOf();
214         else if (f==sn.XSL_DECIMAL_FORMAT) e=new XSLDecimalFormat();
215         else if (f==sn.XSL_DOCUMENT) e=new XSLDocument();
216         else if (f==sn.XSL_ELEMENT) e=new XSLElement();
217         else if (f==sn.XSL_FALLBACK) e=new XSLFallback();
218         else if (f==sn.XSL_FOR_EACH) e=new XSLForEach();
219         else if (f==sn.XSL_IF) e=new XSLIf();
220         else if (f==sn.XSL_IMPORT) e=new XSLImport();
221         else if (f==sn.XSL_INCLUDE) e=new XSLInclude();
222         else if (f==sn.XSL_KEY) e=new XSLKey();
223         else if (f==sn.XSL_MESSAGE) e=new XSLMessage();
224         else if (f==sn.XSL_NUMBER) e=new XSLNumber();
225         else if (f==sn.XSL_NAMESPACE_ALIAS) e=new XSLNamespaceAlias();
226         else if (f==sn.XSL_OTHERWISE) e=new XSLOtherwise();
227         else if (f==sn.XSL_OUTPUT) e=new XSLOutput();
228         else if (f==sn.XSL_PARAM) e=new XSLParam();
229         else if (f==sn.XSL_PRESERVE_SPACE) e=new XSLPreserveSpace();
230         else if (f==sn.XSL_PROCESSING_INSTRUCTION) e=new XSLProcessingInstruction();
231         else if (f==sn.XSL_SCRIPT) e=new XSLScript();
232         else if (f==sn.XSL_SORT) e=new XSLSort();
233         else if (f==sn.XSL_STRIP_SPACE) e=new XSLPreserveSpace();
234         else if (f==sn.XSL_STYLESHEET) e=new XSLStyleSheet();
235         else if (f==sn.XSL_TEMPLATE) e=new XSLTemplate();
236         else if (f==sn.XSL_TEXT) e=new XSLText();
237         else if (f==sn.XSL_TRANSFORM) e=new XSLStyleSheet();
238         else if (f==sn.XSL_VALUE_OF) e=new XSLValueOf();
239         else if (f==sn.XSL_VARIABLE) e=new XSLVariable();
240         else if (f==sn.XSL_WITH_PARAM) e=new XSLWithParam();
241         else if (f==sn.XSL_WHEN) e=new XSLWhen();
242         
243         return e;
244     }
245     
246     /**
247     * Make a SAXON extension element
248     */

249         
250     private StyleElement makeSaxonElement(int f) {
251
252         StyleElement e = null;
253
254         if (f==sn.SAXON_ASSIGN) e=new SAXONAssign();
255         else if (f==sn.SAXON_ENTITY_REF) e=new SAXONEntityRef();
256         else if (f==sn.SAXON_DOCTYPE) e=new SAXONDoctype();
257         else if (f==sn.SAXON_FUNCTION) e=new SAXONFunction();
258         else if (f==sn.SAXON_GROUP) e=new SAXONGroup();
259         else if (f==sn.SAXON_HANDLER) e=new SAXONHandler();
260         else if (f==sn.SAXON_ITEM) e=new SAXONItem();
261         else if (f==sn.SAXON_OUTPUT) e=new XSLDocument(); // synonym
262
else if (f==sn.SAXON_PREVIEW) e=new SAXONPreview();
263         else if (f==sn.SAXON_RETURN) e=new SAXONReturn();
264         else if (f==sn.SAXON_SCRIPT) e=new XSLScript(); // synonym
265
else if (f==sn.SAXON_WHILE) e=new SAXONWhile();
266         return e;
267     }
268
269     /**
270     * Make an EXSLT_FUNCTIONS extension element
271     */

272         
273     private StyleElement makeExsltFunctionsElement(int f) {
274
275         if (f==sn.EXSLT_FUNC_FUNCTION) return new SAXONFunction();
276         else if (f==sn.EXSLT_FUNC_RESULT) return new SAXONReturn();
277         
278         return null;
279     }
280
281     /**
282     * Get the factory class for user extension elements
283     * If there is no appropriate class, return null
284     */

285
286     private ExtensionElementFactory getFactory(short uriCode) {
287         String JavaDoc uri = namePool.getURIFromNamespaceCode(uriCode);
288         int lastSlash = uri.lastIndexOf('/');
289         if (lastSlash<0 || lastSlash==uri.length()-1) {
290             return null;
291         }
292         String JavaDoc factoryClass = uri.substring(lastSlash+1);
293         ExtensionElementFactory factory;
294
295         try {
296             factory = (ExtensionElementFactory)Loader.getInstance(factoryClass);
297         } catch (Exception JavaDoc err) {
298             return null;
299         }
300         return factory;
301     }
302
303     /**
304     * Method to support the element-available() function
305     */

306
307     public boolean isElementAvailable(String JavaDoc uri, String JavaDoc localName) {
308         int fingerprint = namePool.getFingerprint(uri, localName);
309         if (uri.equals(Namespace.XSLT)) {
310             if (fingerprint==-1) return false; // all names are pre-registered
311
StyleElement e = makeXSLElement(fingerprint);
312             if (e!=null) return e.isInstruction();
313         }
314
315         if (uri.equals(Namespace.SAXON)) {
316             if (fingerprint==-1) return false; // all names are pre-registered
317
StyleElement e = makeSaxonElement(fingerprint);
318             if (e!=null) return e.isInstruction();
319         }
320
321         short uriCode = namePool.getCodeForURI(uri);
322         ExtensionElementFactory factory = getFactory(uriCode);
323         if (factory==null) return false;
324         Class JavaDoc actualClass = factory.getExtensionClass(localName);
325         return (actualClass != null);
326
327     }
328
329
330
331
332 }
333
334 //
335
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
336
// you may not use this file except in compliance with the License. You may obtain a copy of the
337
// License at http://www.mozilla.org/MPL/
338
//
339
// Software distributed under the License is distributed on an "AS IS" basis,
340
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
341
// See the License for the specific language governing rights and limitations under the License.
342
//
343
// The Original Code is: all this file.
344
//
345
// The Initial Developer of the Original Code is
346
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
347
//
348
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
349
//
350
// Contributor(s): none.
351
//
352
Popular Tags