KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.style;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.event.LocationProvider;
4 import net.sf.saxon.om.AttributeCollectionImpl;
5 import net.sf.saxon.om.NamePool;
6 import net.sf.saxon.om.NamespaceConstant;
7 import net.sf.saxon.om.NodeInfo;
8 import net.sf.saxon.trans.StaticError;
9 import net.sf.saxon.tree.ElementImpl;
10 import net.sf.saxon.tree.NodeFactory;
11
12 import javax.xml.transform.TransformerException JavaDoc;
13 import javax.xml.transform.TransformerFactoryConfigurationError JavaDoc;
14 import java.math.BigDecimal JavaDoc;
15 import java.util.HashMap JavaDoc;
16
17 /**
18   * Class StyleNodeFactory. <br>
19   * A Factory for nodes in the stylesheet tree. <br>
20   * Currently only allows Element nodes to be user-constructed.
21   * @author Michael H. Kay
22   */

23
24 public class StyleNodeFactory implements NodeFactory {
25
26     HashMap JavaDoc userStyles = new HashMap JavaDoc(4);
27     Configuration config;
28     NamePool namePool;
29     boolean allowExtensions;
30
31
32     public StyleNodeFactory(Configuration config) {
33
34         this.config = config;
35         namePool = config.getNamePool();
36         this.allowExtensions = config.isAllowExternalFunctions();
37     }
38
39     /**
40     * Create an Element node. Note, if there is an error detected while constructing
41     * the Element, we add the element anyway, and return success, but flag the element
42     * with a validation error. This allows us to report more than
43     * one error from a single compilation.
44     * @param nameCode The element name
45     * @param attlist the attribute list
46     */

47
48     public ElementImpl makeElementNode(
49                         NodeInfo parent,
50                         int nameCode,
51                         AttributeCollectionImpl attlist,
52                         int[] namespaces,
53                         int namespacesUsed,
54                         LocationProvider locator,
55                         int locationId,
56                         int sequence)
57     {
58         boolean toplevel = (parent instanceof XSLStylesheet);
59         String JavaDoc baseURI = null;
60         int lineNumber = -1;
61
62         if (locator!=null) {
63             baseURI = locator.getSystemId(locationId);
64             lineNumber = locator.getLineNumber(locationId);
65         }
66
67         if (parent instanceof DataElement) {
68             DataElement d = new DataElement();
69             d.setNamespaceDeclarations(namespaces, namespacesUsed);
70             d.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequence);
71             return d;
72         }
73
74         int f = nameCode&0xfffff;
75
76         // Try first to make an XSLT element
77

78         StyleElement e = makeXSLElement(f);
79
80         if (e != null) { // recognized as an XSLT element
81
try {
82                 e.setNamespaceDeclarations(namespaces, namespacesUsed);
83                 e.setLineNumber(lineNumber);
84                 e.initialise(nameCode, attlist, parent, baseURI, -1, sequence);
85                 e.processDefaultCollationAttribute(StandardNames.DEFAULT_COLLATION);
86                 e.processExtensionElementAttribute(StandardNames.EXTENSION_ELEMENT_PREFIXES);
87                 e.processExcludedNamespaces(StandardNames.EXCLUDE_RESULT_PREFIXES);
88                 e.processVersionAttribute(StandardNames.VERSION);
89                 e.processDefaultXPathNamespaceAttribute(StandardNames.XPATH_DEFAULT_NAMESPACE);
90             } catch (TransformerException JavaDoc err) {
91                 e.setValidationError(err, StyleElement.REPORT_ALWAYS);
92             }
93             return e;
94
95         } else { // not recognized as an XSLT element
96

97             short uriCode = namePool.getURICode(nameCode);
98             String JavaDoc localname = namePool.getLocalName(nameCode);
99             StyleElement temp = null;
100
101             // Detect a misspelt XSLT declaration
102

103             if (uriCode == NamespaceConstant.XSLT_CODE &&
104                     (parent instanceof XSLStylesheet) &&
105                     ((XSLStylesheet)parent).getVersion().compareTo(BigDecimal.valueOf('2')) <= 0 ) {
106                 temp = new AbsentExtensionElement();
107                 temp.setValidationError(new StaticError("Unknown top-level XSLT declaration"),
108                        StyleElement.REPORT_UNLESS_FORWARDS_COMPATIBLE );
109             }
110
111             Class JavaDoc assumedClass = LiteralResultElement.class;
112
113             // We can't work out the final class of the node until we've examined its attributes
114
// such as version and extension-element-prefixes; but we can have a good guess, and
115
// change it later if need be.
116

117
118             boolean assumedSaxonElement = false;
119
120             // recognize Saxon extension elements
121

122             if (temp==null) {
123                 if (uriCode == NamespaceConstant.SAXON_CODE) {
124                     temp = makeSaxonElement(f);
125                     if (temp!=null) {
126                         assumedClass = temp.getClass();
127                         assumedSaxonElement = true;
128                     }
129                 } else if (toplevel && uriCode != 0) {
130                     DataElement d = new DataElement();
131                     d.setNamespaceDeclarations(namespaces, namespacesUsed);
132                     d.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequence);
133                     return d;
134                 }
135             }
136
137             if (temp==null) {
138                 temp = new LiteralResultElement();
139             }
140
141             temp.setNamespaceDeclarations(namespaces, namespacesUsed);
142
143             try {
144                 temp.initialise(nameCode, attlist, parent, baseURI, lineNumber, sequence);
145                 temp.setLineNumber(lineNumber);
146                 temp.processDefaultCollationAttribute(StandardNames.XSL_DEFAULT_COLLATION_CLARK);
147                 temp.processExtensionElementAttribute(StandardNames.XSL_EXTENSION_ELEMENT_PREFIXES_CLARK);
148                 temp.processExcludedNamespaces(StandardNames.XSL_EXCLUDE_RESULT_PREFIXES_CLARK);
149                 temp.processVersionAttribute(StandardNames.XSL_VERSION_CLARK);
150                 temp.processDefaultXPathNamespaceAttribute(StandardNames.XSL_XPATH_DEFAULT_NAMESPACE_CLARK);
151             } catch (TransformerException JavaDoc err) {
152                 temp.setValidationError(err, StyleElement.REPORT_UNLESS_FORWARDS_COMPATIBLE);
153             }
154
155             // Now we work out what class of element we really wanted, and change it if necessary
156

157             TransformerException JavaDoc reason;
158             Class JavaDoc actualClass;
159
160             if (uriCode == NamespaceConstant.XSLT_CODE) {
161                 reason = new StaticError("Unknown XSLT element: " + localname);
162                 ((StaticError)reason).setErrorCode("XTSE0010");
163                 actualClass = AbsentExtensionElement.class;
164                 temp.setValidationError(reason, StyleElement.REPORT_UNLESS_FORWARDS_COMPATIBLE);
165             } else if (uriCode == NamespaceConstant.SAXON_CODE) {
166                 if (toplevel || temp.isExtensionNamespace(uriCode)) {
167                     if (assumedSaxonElement) {
168                         // all is well
169
actualClass = assumedClass;
170                     } else {
171                         actualClass = AbsentExtensionElement.class;
172                         reason = new StaticError(
173                                         "Unknown Saxon extension element: " + localname);
174                         temp.setValidationError(reason, StyleElement.REPORT_IF_INSTANTIATED);
175                     }
176                 } else {
177                     actualClass = LiteralResultElement.class;
178                 }
179             } else if (temp.isExtensionNamespace(uriCode) && !toplevel) {
180                 Integer JavaDoc nameKey = new Integer JavaDoc(nameCode&0xfffff);
181
182                 actualClass = (Class JavaDoc)userStyles.get(nameKey);
183                 if (actualClass==null) {
184                     if (allowExtensions) {
185                         ExtensionElementFactory factory = getFactory(uriCode);
186                         if (factory != null) {
187                             actualClass = factory.getExtensionClass(localname);
188                             if (actualClass != null) {
189                                 userStyles.put(nameKey, actualClass); // for quicker access next time
190
}
191                         }
192                     } else {
193                         actualClass = AbsentExtensionElement.class;
194                         reason = new StaticError("Extension elements are disabled");
195                         temp.setValidationError(reason, StyleElement.REPORT_IF_INSTANTIATED);
196                     }
197
198                     if (actualClass == null) {
199
200                         // if we can't instantiate an extension element, we don't give up
201
// immediately, because there might be an xsl:fallback defined. We
202
// create a surrogate element called AbsentExtensionElement, and
203
// save the reason for failure just in case there is no xsl:fallback
204

205                         actualClass = AbsentExtensionElement.class;
206                         StaticError se = new StaticError("Unknown extension element", temp);
207                         se.setErrorCode("XTDE1450");
208                         reason = se;
209                         temp.setValidationError(reason, StyleElement.REPORT_IF_INSTANTIATED);
210                     }
211                 }
212             } else {
213                 actualClass = LiteralResultElement.class;
214             }
215
216             StyleElement node;
217             if (actualClass.equals(assumedClass)) {
218                 node = temp; // the original element will do the job
219
} else {
220                 try {
221                     node = (StyleElement)actualClass.newInstance();
222                 } catch (InstantiationException JavaDoc err1) {
223                     throw new TransformerFactoryConfigurationError JavaDoc(err1, "Failed to create instance of " + actualClass.getName());
224                 } catch (IllegalAccessException JavaDoc err2) {
225                     throw new TransformerFactoryConfigurationError JavaDoc(err2, "Failed to access class " + actualClass.getName());
226                 }
227                 node.substituteFor(temp); // replace temporary node with the new one
228
}
229             return node;
230         }
231     }
232
233     /**
234     * Make an XSL element node
235     */

236
237     private StyleElement makeXSLElement(int f) {
238         switch (f) {
239         case StandardNames.XSL_ANALYZE_STRING:
240             return new XSLAnalyzeString();
241         case StandardNames.XSL_APPLY_IMPORTS:
242             return new XSLApplyImports();
243         case StandardNames.XSL_APPLY_TEMPLATES:
244             return new XSLApplyTemplates();
245         case StandardNames.XSL_ATTRIBUTE:
246             return new XSLAttribute();
247         case StandardNames.XSL_ATTRIBUTE_SET:
248             return new XSLAttributeSet();
249         case StandardNames.XSL_CALL_TEMPLATE:
250             return new XSLCallTemplate();
251         case StandardNames.XSL_CHARACTER_MAP:
252             return new XSLCharacterMap();
253         case StandardNames.XSL_CHOOSE:
254             return new XSLChoose();
255         case StandardNames.XSL_COMMENT:
256             return new XSLComment();
257         case StandardNames.XSL_COPY:
258             return new XSLCopy();
259         case StandardNames.XSL_COPY_OF:
260             return new XSLCopyOf();
261         case StandardNames.XSL_DECIMAL_FORMAT:
262             return new XSLDecimalFormat();
263         case StandardNames.XSL_DOCUMENT:
264             return new XSLDocument();
265         case StandardNames.XSL_ELEMENT:
266             return new XSLElement();
267         case StandardNames.XSL_FALLBACK:
268             return new XSLFallback();
269         case StandardNames.XSL_FOR_EACH:
270             return new XSLForEach();
271         case StandardNames.XSL_FOR_EACH_GROUP:
272             return new XSLForEachGroup();
273         case StandardNames.XSL_FUNCTION:
274             return new XSLFunction();
275         case StandardNames.XSL_IF:
276             return new XSLIf();
277         case StandardNames.XSL_IMPORT:
278             return new XSLImport();
279         case StandardNames.XSL_IMPORT_SCHEMA:
280             return new XSLImportSchema();
281         case StandardNames.XSL_INCLUDE:
282             return new XSLInclude();
283         case StandardNames.XSL_KEY:
284             return new XSLKey();
285         case StandardNames.XSL_MATCHING_SUBSTRING:
286             return new XSLMatchingSubstring();
287         case StandardNames.XSL_MESSAGE:
288             return new XSLMessage();
289         case StandardNames.XSL_NEXT_MATCH:
290             return new XSLNextMatch();
291         case StandardNames.XSL_NON_MATCHING_SUBSTRING:
292             return new XSLMatchingSubstring(); //sic
293
case StandardNames.XSL_NUMBER:
294             return new XSLNumber();
295         case StandardNames.XSL_NAMESPACE:
296             return new XSLNamespace();
297         case StandardNames.XSL_NAMESPACE_ALIAS:
298             return new XSLNamespaceAlias();
299         case StandardNames.XSL_OTHERWISE:
300             return new XSLOtherwise();
301         case StandardNames.XSL_OUTPUT:
302             return new XSLOutput();
303         case StandardNames.XSL_OUTPUT_CHARACTER:
304             return new XSLOutputCharacter();
305         case StandardNames.XSL_PARAM:
306             return new XSLParam();
307         case StandardNames.XSL_PERFORM_SORT:
308             return new XSLPerformSort();
309         case StandardNames.XSL_PRESERVE_SPACE:
310             return new XSLPreserveSpace();
311         case StandardNames.XSL_PROCESSING_INSTRUCTION:
312             return new XSLProcessingInstruction();
313         case StandardNames.XSL_RESULT_DOCUMENT:
314             return new XSLResultDocument();
315         case StandardNames.XSL_SEQUENCE:
316             return new XSLSequence();
317         case StandardNames.XSL_SORT:
318             return new XSLSort();
319         case StandardNames.XSL_STRIP_SPACE:
320             return new XSLPreserveSpace();
321         case StandardNames.XSL_STYLESHEET:
322             return new XSLStylesheet();
323         case StandardNames.XSL_TEMPLATE:
324             return new XSLTemplate();
325         case StandardNames.XSL_TEXT:
326             return new XSLText();
327         case StandardNames.XSL_TRANSFORM:
328             return new XSLStylesheet();
329         case StandardNames.XSL_VALUE_OF:
330             return new XSLValueOf();
331         case StandardNames.XSL_VARIABLE:
332             return new XSLVariable();
333         case StandardNames.XSL_WITH_PARAM:
334             return new XSLWithParam();
335         case StandardNames.XSL_WHEN:
336             return new XSLWhen();
337         default: return null;
338         }
339     }
340
341     /**
342     * Make a SAXON extension element
343     */

344
345     private StyleElement makeSaxonElement(int f) {
346
347         switch (f) {
348
349         case StandardNames.SAXON_ASSIGN:
350             return new SaxonAssign();
351         case StandardNames.SAXON_ENTITY_REF:
352             return new SaxonEntityRef();
353         case StandardNames.SAXON_CALL_TEMPLATE:
354             return new SaxonCallTemplate();
355         case StandardNames.SAXON_COLLATION:
356             return new SaxonCollation();
357         case StandardNames.SAXON_DOCTYPE:
358             return new SaxonDoctype();
359         case StandardNames.SAXON_IMPORT_QUERY:
360             return new SaxonImportQuery();
361         case StandardNames.SAXON_SCRIPT:
362             return new SaxonScript();
363         case StandardNames.SAXON_WHILE:
364             return new SaxonWhile();
365         default: return null;
366         }
367     }
368
369     /**
370     * Get the factory class for user extension elements
371     * If there is no appropriate class, return null
372     */

373
374     private ExtensionElementFactory getFactory(short uriCode) {
375         String JavaDoc uri = namePool.getURIFromNamespaceCode(uriCode);
376         int lastSlash = uri.lastIndexOf('/');
377         if (lastSlash<0 || lastSlash==uri.length()-1) {
378             return null;
379         }
380         String JavaDoc factoryClass = uri.substring(lastSlash+1);
381         ExtensionElementFactory factory;
382
383         try {
384             factory = (ExtensionElementFactory)config.getInstance(factoryClass, null);
385         } catch (Exception JavaDoc err) {
386             return null;
387         }
388         return factory;
389     }
390
391     /**
392     * Method to support the element-available() function
393     */

394
395     public boolean isElementAvailable(String JavaDoc uri, String JavaDoc localName) {
396         int fingerprint = namePool.getFingerprint(uri, localName);
397         if (uri.equals(NamespaceConstant.XSLT)) {
398             if (fingerprint==-1) return false; // all names are pre-registered
399
StyleElement e = makeXSLElement(fingerprint);
400             if (e!=null) return e.isInstruction();
401         }
402
403         if (uri.equals(NamespaceConstant.SAXON)) {
404             if (fingerprint==-1) return false; // all names are pre-registered
405
StyleElement e = makeSaxonElement(fingerprint);
406             if (e!=null) return e.isInstruction();
407         }
408         if (!allowExtensions) {
409             // extension elements are disabled
410
return false;
411         }
412         short uriCode = namePool.getCodeForURI(uri);
413         ExtensionElementFactory factory = getFactory(uriCode);
414         if (factory==null) return false;
415         Class JavaDoc actualClass = factory.getExtensionClass(localName);
416         return (actualClass != null);
417
418     }
419
420
421
422
423 }
424
425 //
426
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
427
// you may not use this file except in compliance with the License. You may obtain a copy of the
428
// License at http://www.mozilla.org/MPL/
429
//
430
// Software distributed under the License is distributed on an "AS IS" basis,
431
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
432
// See the License for the specific language governing rights and limitations under the License.
433
//
434
// The Original Code is: all this file.
435
//
436
// The Initial Developer of the Original Code is Michael H. Kay.
437
//
438
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
439
//
440
// Contributor(s): none.
441
//
442
Popular Tags