View Javadoc

1   /*
2    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
3    * 
4    * This software is open source. 
5    * See the bottom of this file for the licence.
6    * 
7    * $Id: DatatypeDocumentFactory.java,v 1.7 2004/06/25 08:03:34 maartenc Exp $
8    */
9   
10  package org.dom4j.datatype;
11  
12  import org.dom4j.Attribute;
13  import org.dom4j.Document;
14  import org.dom4j.DocumentFactory;
15  import org.dom4j.Element;
16  import org.dom4j.Namespace;
17  import org.dom4j.QName;
18  import org.dom4j.io.SAXReader;
19  import org.xml.sax.EntityResolver;
20  import org.xml.sax.InputSource;
21  
22  /*** <p><code>DatatypeDocumentFactory</code> is a factory of XML objects which 
23    * support the 
24    * <a href="http://www.w3.org/TR/xmlschema-2/">XML Schema Data Types</a>
25    * specification.</p>
26    *
27    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
28    * @version $Revision: 1.7 $
29    */
30  public class DatatypeDocumentFactory extends DocumentFactory {
31  
32      
33      // XXXX: I don't think interning of QNames is necessary
34      private static final boolean DO_INTERN_QNAME = false;
35      
36      
37      /*** The Singleton instance */
38      static transient DatatypeDocumentFactory singleton = new DatatypeDocumentFactory();
39      
40      private static final Namespace XSI_NAMESPACE
41          = Namespace.get( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
42      
43      private static final QName XSI_SCHEMA_LOCATION
44          = QName.get( "schemaLocation", XSI_NAMESPACE );
45      
46      private static final QName XSI_NO_SCHEMA_LOCATION
47          = QName.get( "noNamespaceSchemaLocation", XSI_NAMESPACE );
48      
49  
50      /*** The builder of XML Schemas */
51      private SchemaParser schemaBuilder;
52      
53      /*** reader of XML Schemas */
54      private SAXReader xmlSchemaReader = new SAXReader();
55  
56      
57      /*** If schemas are automatically loaded when parsing instance documents */
58      private boolean autoLoadSchema = true;
59      
60      
61      /*** <p>Access to the singleton instance of this factory.</p>
62        *
63        * @return the default singleon instance
64        */
65      public static DocumentFactory getInstance() {
66          return singleton;
67      }
68      
69      public DatatypeDocumentFactory() {
70          schemaBuilder = new SchemaParser(this);
71      }
72  
73      
74      /*** Loads the given XML Schema document into this factory so
75        * schema-aware Document, Elements and Attributes will be created
76        * by this factory.
77        *
78        * @param schemaDocument is an XML Schema Document instance.
79        */
80      public void loadSchema(Document schemaDocument) {
81          schemaBuilder.build( schemaDocument );
82      }
83      
84      public void loadSchema(Document schemaDocument, Namespace targetNamespace) {
85          schemaBuilder.build( schemaDocument, targetNamespace );
86      }
87      
88      /*** Registers the given <code>DatatypeElementFactory</code> for the given 
89        * &lt;element&gt; schema element
90        */
91      public DatatypeElementFactory getElementFactory( QName elementQName ) {
92          if ( DO_INTERN_QNAME ) {
93              elementQName = intern( elementQName );
94          }
95          DocumentFactory factory = elementQName.getDocumentFactory();
96          return (factory instanceof DatatypeElementFactory) 
97              ? (DatatypeElementFactory) factory : null;
98      }
99      
100         
101     // DocumentFactory methods
102     //-------------------------------------------------------------------------
103 /*    
104     public Element createElement(QName qname) {
105         DocumentFactory elementFactory = qname.getDocumentFactory();
106         if ( elementFactory != null ) {
107             return elementFactory.createElement(qname);
108         }
109         return super.createElement(qname);
110     }
111 */    
112     public Attribute createAttribute(Element owner, QName qname, String value) {
113         if ( autoLoadSchema && qname.equals( XSI_NO_SCHEMA_LOCATION ) ) {
114             Document document = (owner != null) ? owner.getDocument() : null;
115             loadSchema( document, value );
116         }
117         else if ( autoLoadSchema && qname.equals( XSI_SCHEMA_LOCATION ) ) 
118         { 
119             Document document = (owner != null) ? owner.getDocument() : null; 
120             Namespace namespace = owner.getNamespaceForURI(value.substring(0,value.indexOf(' '))); 
121             loadSchema( document, value.substring (value.indexOf(' ')+1), namespace ); 
122         } 
123 
124         return super.createAttribute( owner, qname, value );
125     }
126     
127 
128     
129     // Implementation methods
130     //-------------------------------------------------------------------------
131     protected void loadSchema( Document document, String schemaInstanceURI ) {
132         try {
133             EntityResolver resolver = document.getEntityResolver();
134             if ( resolver == null ) {
135                 throw new InvalidSchemaException( "No EntityResolver available so could not resolve the schema URI: " + schemaInstanceURI );
136             }
137             InputSource inputSource = resolver.resolveEntity( null, schemaInstanceURI );
138             if ( resolver == null ) {
139                 throw new InvalidSchemaException( "Could not resolve the schema URI: " + schemaInstanceURI );
140             }
141             Document schemaDocument = xmlSchemaReader.read( inputSource );
142             loadSchema( schemaDocument );
143         }
144         catch (Exception e) {
145             System.out.println( "Failed to load schema: " + schemaInstanceURI );
146             System.out.println( "Caught: " + e );
147             e.printStackTrace();
148             throw new InvalidSchemaException( "Failed to load schema: " + schemaInstanceURI );
149         }
150     }
151     
152     protected void loadSchema( Document document, String schemaInstanceURI, Namespace namespace ) {
153         try {
154             EntityResolver resolver = document.getEntityResolver();
155             if ( resolver == null ) {
156                 throw new InvalidSchemaException( "No EntityResolver available so could not resolve the schema URI: " + schemaInstanceURI );
157             }
158             InputSource inputSource = resolver.resolveEntity( null, schemaInstanceURI );
159             if ( resolver == null ) {
160                 throw new InvalidSchemaException( "Could not resolve the schema URI: " + schemaInstanceURI );
161             }
162             Document schemaDocument = xmlSchemaReader.read( inputSource );
163             loadSchema( schemaDocument, namespace );
164         }
165         catch (Exception e) {
166             System.out.println( "Failed to load schema: " + schemaInstanceURI );
167             System.out.println( "Caught: " + e );
168             e.printStackTrace();
169             throw new InvalidSchemaException( "Failed to load schema: " + schemaInstanceURI );
170         }
171     }
172 }
173 
174 
175 
176 
177 /*
178  * Redistribution and use of this software and associated documentation
179  * ("Software"), with or without modification, are permitted provided
180  * that the following conditions are met:
181  *
182  * 1. Redistributions of source code must retain copyright
183  *    statements and notices.  Redistributions must also contain a
184  *    copy of this document.
185  *
186  * 2. Redistributions in binary form must reproduce the
187  *    above copyright notice, this list of conditions and the
188  *    following disclaimer in the documentation and/or other
189  *    materials provided with the distribution.
190  *
191  * 3. The name "DOM4J" must not be used to endorse or promote
192  *    products derived from this Software without prior written
193  *    permission of MetaStuff, Ltd.  For written permission,
194  *    please contact dom4j-info@metastuff.com.
195  *
196  * 4. Products derived from this Software may not be called "DOM4J"
197  *    nor may "DOM4J" appear in their names without prior written
198  *    permission of MetaStuff, Ltd. DOM4J is a registered
199  *    trademark of MetaStuff, Ltd.
200  *
201  * 5. Due credit should be given to the DOM4J Project - 
202  *    http://www.dom4j.org
203  *
204  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
205  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
206  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
207  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
208  * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
209  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
210  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
211  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
213  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
214  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
215  * OF THE POSSIBILITY OF SUCH DAMAGE.
216  *
217  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
218  *
219  * $Id: DatatypeDocumentFactory.java,v 1.7 2004/06/25 08:03:34 maartenc Exp $
220  */