upstream version 1.2.2
[debian/freetts] / com / sun / speech / engine / synthesis / JSMLParser.java
1 /**
2  * Copyright 1998-2001 Sun Microsystems, Inc.
3  * 
4  * See the file "license.terms" for information on usage and
5  * redistribution of this file, and for a DISCLAIMER OF ALL 
6  * WARRANTIES.
7  */
8 package com.sun.speech.engine.synthesis;
9
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.StringReader;
13 import java.net.URL;
14
15 import javax.speech.synthesis.JSMLException;
16 import javax.xml.parsers.DocumentBuilder;
17 import javax.xml.parsers.DocumentBuilderFactory;
18 import javax.xml.parsers.ParserConfigurationException;
19
20 import org.w3c.dom.Document;
21 import org.xml.sax.InputSource;
22 import org.xml.sax.SAXException;
23
24 /**
25  * Parses a JSML 0.6 document and returns a DOM.
26  */
27 public class JSMLParser {
28     private DocumentBuilder validatingDocumentBuilder;
29
30     private DocumentBuilder nonvalidatingDocumentBuilder;
31
32     /**
33      * The DOM.
34      */
35     Document document;
36     
37     /**
38      * Creates a new JSMLParser for the given JSML
39      * text.  Parses the text immediately and return any errors.
40      * The resulting DOM Document can be retrieved via
41      * <code>getDocument</code>.
42      * The optional validate will do validation of the JSML text.
43      * This is typically not used since JSML doesn't require validation.
44      *
45      * @param jsmlText the JSML text
46      * @param validate if <code>true</code>, validate the JSML text
47      *
48      * @see #getDocument
49      *
50      * @throws JSMLException if the JSML text contains errors
51      */
52     public JSMLParser(String jsmlText, boolean validate)
53         throws JSMLException {
54
55         // Handle case where text does not include a root element
56         //
57         if (!(jsmlText.substring(0,2).equals("<?"))) {
58             jsmlText = "<jsml>\n" + jsmlText + "</jsml>\n";
59         }
60
61         try {
62             document = parse(new InputSource(new StringReader(jsmlText)),
63                              validate);
64         } catch (IOException e) {
65             throw new JSMLException("JSMLParser: " + e.getMessage());
66         }
67     }
68
69     /**
70      * Creates a new JSMLParser for the given <code>URL</code>.
71      * Parses the text immediately and returns any errors.
72      * The resulting DOM Document can be retrieved via
73      * <code>getDocument</code>.
74      * The optional validate will do validation of the JSML text.
75      * This is typically not used since JSML doesn't require validation.
76      *
77      * @param jsmlSource the URL containing JSML text
78      * @param validate if <code>true</code>, validate the JSML text
79      *
80      * @see #getDocument
81      *
82      * @throws JSMLException if the JSML text contains errors
83      * @throws IOException if problems encountered with URL
84      */
85     public JSMLParser(URL jsmlSource, boolean validate) 
86         throws JSMLException, IOException {
87         final InputStream in = jsmlSource.openStream();
88         final InputSource source = new InputSource(in);
89         document = parse(source, validate);
90     }
91
92     /**
93      * Gets the document for this parser.
94      *
95      * @return a DOM
96      */
97     public Document getDocument() {
98         return document;
99     }
100
101     /**
102      * Lazy instantiation of the document builder.
103      * @param validate <code>true</code> if the document builder should be
104      *          validating.
105      * @return document builder to use
106      * @throws JSMLException
107      *         error creating the document builder.
108      */
109     private DocumentBuilder getDocumentBuilder(boolean validate)
110         throws JSMLException {
111         if (validate && (validatingDocumentBuilder != null)) {
112             return validatingDocumentBuilder;
113         } else if (!validate && (nonvalidatingDocumentBuilder != null)) {
114             return nonvalidatingDocumentBuilder;
115         }
116         final DocumentBuilderFactory dbf =
117             DocumentBuilderFactory.newInstance();
118
119         dbf.setValidating(validate);
120         dbf.setIgnoringComments(true);
121         dbf.setIgnoringElementContentWhitespace(false);
122         dbf.setCoalescing(true);
123         dbf.setExpandEntityReferences(true);
124
125         try {
126             DocumentBuilder db = dbf.newDocumentBuilder();
127             if (validate) {
128                 validatingDocumentBuilder = db;
129             } else {
130                 nonvalidatingDocumentBuilder = db;
131             }
132             return db;
133         } catch (ParserConfigurationException e) {
134             throw new JSMLException(
135                 "JSMLParser: " + e.getMessage());
136         }
137     }
138
139     /**
140      * Parses the source and optionally validates it.
141      *
142      * @param source the JSML text
143      * @param validate if <code>true</code>, validate the JSML text
144      *
145      * @throws JSMLException if the JSML text contains errors
146      * @throws IOException if problems encountered with <code>source</code>
147      */
148     protected Document parse(InputSource source, boolean validate)
149         throws JSMLException, IOException {
150         final DocumentBuilder db = getDocumentBuilder(validate);
151         final Document doc;
152         try {
153             doc = db.parse(source);
154         } catch (SAXException e) {
155             throw new JSMLException("JSMLParser: " + e.getMessage());
156         }
157         return doc;
158     }
159 }