KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > dtd > grammar > DTDParser


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.dtd.grammar;
21
22 import java.io.*;
23 import java.util.*;
24 import java.util.StringTokenizer JavaDoc;
25
26 import org.xml.sax.*;
27 import org.xml.sax.ext.*;
28 import org.xml.sax.helpers.*;
29
30 import org.openide.xml.*;
31 import org.openide.util.Lookup;
32
33 import org.netbeans.api.xml.parsers.SAXEntityParser;
34 import org.netbeans.api.xml.services.UserCatalog;
35 import org.netbeans.modules.xml.api.model.GrammarQuery;
36
37
38 /**
39  * Produces {@link DTDGrammar} from passed SAX declaration handler events.
40  *
41  * @author Petr Kuzel
42  * @author asgeir@dimonsoftware.com
43  */

44 public class DTDParser {
45     
46     static final String JavaDoc SAX_PROPERTY = "http://xml.org/sax/properties/"; //NOI18N
47
static final String JavaDoc DECL_HANDLER = "declaration-handler"; //NOI18N
48

49     /** If true, the InputSource parameter of the parse method is expected to be a
50      * DTD document, otherwise if is expected to be a XML document. */

51     private boolean dtdOnly;
52     
53     /** Creates new DTDParser
54      * The InputSource parameter of the parse method should be a XML document
55      */

56     public DTDParser() {
57         this(false);
58     }
59     
60     /** Creates new DTDParser
61      * @param dtdOnly If true the InputSource parameter into the parse method
62      * should be a DTD document, otherwise it should be an XML
63      * document.
64      */

65     public DTDParser(boolean dtdOnly) {
66         this.dtdOnly = dtdOnly;
67     }
68     
69     public GrammarQuery parse(InputSource in) {
70         
71         Handler handler = new Handler();
72         
73         EntityResolverWrapper res = null;
74         try {
75             XMLReader parser = XMLUtil.createXMLReader(dtdOnly == false); // we do not want Crimson, it does not understand relative SYSTEM ids
76
parser.setContentHandler(handler);
77             parser.setErrorHandler(handler);
78             parser.setDTDHandler(handler);
79             
80             UserCatalog catalog = UserCatalog.getDefault();
81             if(catalog != null) {
82                 res = new EntityResolverWrapper(catalog.getEntityResolver());
83             };
84             
85             if (res != null) {
86                 parser.setEntityResolver(res);
87             }
88             parser.setProperty(SAX_PROPERTY + DECL_HANDLER, handler);
89             
90             if (dtdOnly) {
91                 new SAXEntityParser(parser, false).parse(in);
92             } else {
93                 parser.parse(in);
94             }
95             throw new IllegalStateException JavaDoc("How we can get here?");
96         } catch (Stop stop) {
97             //OK
98
} catch (SAXException ex) {
99             if (Boolean.getBoolean("netbeans.debug.xml") || Boolean.getBoolean("netbeans.debug.exceptions")) { //NOI18N
100
ex.printStackTrace();
101                 if (ex.getException() instanceof RuntimeException JavaDoc) {
102                     ex.getException().printStackTrace(); //???
103
}
104             }
105             //error, but return what was parsed
106
} catch (IOException ex) {
107             if (Boolean.getBoolean("netbeans.debug.xml")) { // NOI18N
108
ex.printStackTrace();
109             }
110             //error, but return at least a partial result
111
}
112
113         DTDGrammar dtdGrammar = handler.getDTDGrammar();
114         dtdGrammar.setResolvedEntities(res.getResolvedSystemIds());
115         return dtdGrammar;
116     }
117         
118     /**
119      * Actually create a grammar from callback information.
120      */

121     private class Handler extends DefaultHandler implements DeclHandler {
122         
123         private Map attrs, elements, models, enums, attrDefaults;
124         private Set notations, entities, anys, emptyElements;
125         private DTDGrammar dtd;
126         
127         Handler() {
128             attrs = new HashMap();
129             elements = new HashMap();
130             models = new HashMap();
131             notations = new TreeSet();
132             entities = new TreeSet();
133             anys = new HashSet();
134             enums = new HashMap();
135             attrDefaults = new HashMap();
136             emptyElements = new HashSet();
137             dtd = new DTDGrammar(elements, models, attrs, attrDefaults, enums, entities, notations, emptyElements);
138         }
139         
140         /**
141          * Update value of ANY declared content models
142          */

143         DTDGrammar getDTDGrammar() {
144             Iterator it = anys.iterator();
145             while (it.hasNext()) {
146                 String JavaDoc name = (String JavaDoc) it.next();
147                 elements.put(name, elements.keySet());
148             }
149             
150             return dtd;
151         }
152         
153         public void elementDecl(String JavaDoc name, String JavaDoc model) throws SAXException {
154             
155             // special cases
156

157             if ("ANY".equals(model)) {
158                 anys.add(name);
159                 elements.put(name, Collections.EMPTY_SET); // see anys resolving
160
return;
161             } else if ("EMPTY".equals(model)) {
162                 elements.put(name, Collections.EMPTY_SET);
163                 emptyElements.add(name);
164                 return;
165             } else if ("(#PCDATA)".equals(model)) {
166                 elements.put(name, Collections.EMPTY_SET);
167                 return;
168             }
169             
170             // parse content model
171

172             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(model, " \t\n|,()?+*");
173             Set modelset = new TreeSet();
174             while (tokenizer.hasMoreTokens()) {
175                 String JavaDoc next = tokenizer.nextToken().trim();
176                 if ("#PCDATA".equals(next)) continue;
177                 modelset.add(next);
178             }
179             
180             elements.put(name, modelset);
181             models.put(name, model);
182         }
183         
184         public void externalEntityDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) throws SAXException {
185             if (name.startsWith("%")) return; // NOI18N
186
entities.add(name);
187         }
188         
189         public void attributeDecl(String JavaDoc eName, String JavaDoc aName, String JavaDoc type, String JavaDoc valueDefault, String JavaDoc value) throws SAXException {
190             Set set = (Set) attrs.get(eName);
191             if (set == null) {
192                 set = new TreeSet();
193                 attrs.put(eName, set);
194             }
195             set.add(aName);
196             
197             // if enumeration type place into enumeration map new entry
198
if (type != null && type.startsWith("(")) {
199                 StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(type, "()|", false);
200                 List tokens = new ArrayList(7);
201                 while (tokenizer.hasMoreTokens()) {
202                     tokens.add(tokenizer.nextToken());
203                 }
204                 enums.put(eName + " " + aName, tokens); // NOI18N
205
}
206             
207             // store defaults
208
String JavaDoc key = eName + " " + aName; // NOI18N
209
attrDefaults.put(key, valueDefault);
210         }
211         
212         public void internalEntityDecl(String JavaDoc name, String JavaDoc value) throws SAXException {
213             if (name.startsWith("%")) return; // NOI18N
214
entities.add(name);
215         }
216         
217         public void notationDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) throws SAXException {
218             notations.add(name);
219         }
220         
221         public void startElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes atts) throws SAXException {
222             throw new Stop();
223         }
224         
225     }
226     
227     
228     private class Stop extends SAXException {
229         
230         private static final long serialVersionUID = -6466279601744402792L;
231         
232         Stop() {
233             super("STOP"); //NOI18N
234
}
235         
236         public Throwable JavaDoc fillInStackTrace() {
237             return this;
238         }
239     }
240     
241     private class EntityResolverWrapper implements EntityResolver {
242         
243         private EntityResolver resolver;
244         private ArrayList/*<String>*/ resolvedSystemIds = new ArrayList(3);
245         
246         public EntityResolverWrapper(EntityResolver resolver) {
247             this.resolver = resolver;
248         }
249         
250         public InputSource resolveEntity(String JavaDoc publicId, String JavaDoc systemId) throws SAXException, IOException {
251             resolvedSystemIds.add(systemId);
252             return resolver.resolveEntity(publicId, systemId);
253         }
254         
255         public List/*<String>*/ getResolvedSystemIds() {
256             return resolvedSystemIds;
257         }
258         
259     }
260 }
261
Popular Tags