1   
2   
3   
4   
5   
6   
7   
8   package org.dom4j.datatype;
9   
10  import org.dom4j.Attribute;
11  import org.dom4j.Document;
12  import org.dom4j.DocumentFactory;
13  import org.dom4j.Element;
14  import org.dom4j.Namespace;
15  import org.dom4j.QName;
16  import org.dom4j.io.SAXReader;
17  
18  import org.xml.sax.EntityResolver;
19  import org.xml.sax.InputSource;
20  
21  /***
22   * <p>
23   * <code>DatatypeDocumentFactory</code> is a factory of XML objects which
24   * support the <a href="http://www.w3.org/TR/xmlschema-2/">XML Schema Data Types
25   * </a> specification.
26   * </p>
27   * 
28   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
29   * @version $Revision: 1.9 $
30   */
31  public class DatatypeDocumentFactory extends DocumentFactory {
32      
33      private static final boolean DO_INTERN_QNAME = false;
34  
35      /*** The Singleton instance */
36      protected static transient DatatypeDocumentFactory singleton 
37              = new DatatypeDocumentFactory();
38  
39      private static final Namespace XSI_NAMESPACE = Namespace.get("xsi",
40              "http://www.w3.org/2001/XMLSchema-instance");
41  
42      private static final QName XSI_SCHEMA_LOCATION = QName.get(
43              "schemaLocation", XSI_NAMESPACE);
44  
45      private static final QName XSI_NO_SCHEMA_LOCATION = QName.get(
46              "noNamespaceSchemaLocation", XSI_NAMESPACE);
47  
48      /*** The builder of XML Schemas */
49      private SchemaParser schemaBuilder;
50  
51      /*** reader of XML Schemas */
52      private SAXReader xmlSchemaReader = new SAXReader();
53  
54      /*** If schemas are automatically loaded when parsing instance documents */
55      private boolean autoLoadSchema = true;
56  
57      public DatatypeDocumentFactory() {
58          schemaBuilder = new SchemaParser(this);
59      }
60  
61      /***
62       * <p>
63       * Access to the singleton instance of this factory.
64       * </p>
65       * 
66       * @return the default singleon instance
67       */
68      public static DocumentFactory getInstance() {
69          return singleton;
70      }
71  
72      /***
73       * Loads the given XML Schema document into this factory so schema-aware
74       * Document, Elements and Attributes will be created by this factory.
75       * 
76       * @param schemaDocument
77       *            is an XML Schema Document instance.
78       */
79      public void loadSchema(Document schemaDocument) {
80          schemaBuilder.build(schemaDocument);
81      }
82  
83      public void loadSchema(Document schemaDocument, Namespace targetNamespace) {
84          schemaBuilder.build(schemaDocument, targetNamespace);
85      }
86  
87      /***
88       * Registers the given <code>DatatypeElementFactory</code> for the given
89       * <element> schema element
90       * 
91       * @param elementQName
92       *            DOCUMENT ME!
93       * 
94       * @return DOCUMENT ME!
95       */
96      public DatatypeElementFactory getElementFactory(QName elementQName) {
97          DatatypeElementFactory result = null;
98          
99          if (DO_INTERN_QNAME) {
100             elementQName = intern(elementQName);
101         }
102 
103         DocumentFactory factory = elementQName.getDocumentFactory();
104         if (factory instanceof DatatypeElementFactory) {
105             result = (DatatypeElementFactory) factory;
106         }
107         
108         return result;
109     }
110 
111     
112     
113     public Attribute createAttribute(Element owner, QName qname, String value) {
114         if (autoLoadSchema && qname.equals(XSI_NO_SCHEMA_LOCATION)) {
115             Document document = (owner != null) ? owner.getDocument() : null;
116             loadSchema(document, value);
117         } else if (autoLoadSchema && qname.equals(XSI_SCHEMA_LOCATION)) {
118             Document document = (owner != null) ? owner.getDocument() : null;
119             String uri = value.substring(0, value.indexOf(' '));
120             Namespace namespace = owner.getNamespaceForURI(uri);
121             loadSchema(document, value.substring(value.indexOf(' ') + 1),
122                     namespace);
123         }
124 
125         return super.createAttribute(owner, qname, value);
126     }
127 
128     
129     
130     protected void loadSchema(Document document, String schemaInstanceURI) {
131         try {
132             EntityResolver resolver = document.getEntityResolver();
133 
134             if (resolver == null) {
135                 String msg = "No EntityResolver available for resolving URI: ";
136                 throw new InvalidSchemaException(msg + schemaInstanceURI);
137             }
138 
139             InputSource inputSource = resolver.resolveEntity(null,
140                     schemaInstanceURI);
141 
142             if (resolver == null) {
143                 throw new InvalidSchemaException("Could not resolve the URI: "
144                         + schemaInstanceURI);
145             }
146 
147             Document schemaDocument = xmlSchemaReader.read(inputSource);
148             loadSchema(schemaDocument);
149         } catch (Exception e) {
150             System.out.println("Failed to load schema: " + schemaInstanceURI);
151             System.out.println("Caught: " + e);
152             e.printStackTrace();
153             throw new InvalidSchemaException("Failed to load schema: "
154                     + schemaInstanceURI);
155         }
156     }
157 
158     protected void loadSchema(Document document, String schemaInstanceURI,
159             Namespace namespace) {
160         try {
161             EntityResolver resolver = document.getEntityResolver();
162 
163             if (resolver == null) {
164                 String msg = "No EntityResolver available for resolving URI: ";
165                 throw new InvalidSchemaException(msg + schemaInstanceURI);
166             }
167 
168             InputSource inputSource = resolver.resolveEntity(null,
169                     schemaInstanceURI);
170 
171             if (resolver == null) {
172                 throw new InvalidSchemaException("Could not resolve the URI: "
173                         + schemaInstanceURI);
174             }
175 
176             Document schemaDocument = xmlSchemaReader.read(inputSource);
177             loadSchema(schemaDocument, namespace);
178         } catch (Exception e) {
179             System.out.println("Failed to load schema: " + schemaInstanceURI);
180             System.out.println("Caught: " + e);
181             e.printStackTrace();
182             throw new InvalidSchemaException("Failed to load schema: "
183                     + schemaInstanceURI);
184         }
185     }
186 }
187 
188 
189 
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223