2 Copyright (C) 2001,2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import org
.w3c
.dom
.DocumentType
;
42 import org
.w3c
.dom
.Node
;
43 import org
.w3c
.dom
.Text
;
45 import org
.xml
.sax
.Attributes
;
46 import org
.xml
.sax
.SAXException
;
47 import org
.xml
.sax
.ext
.Attributes2
;
49 import gnu
.xml
.pipeline
.DomConsumer
;
50 import gnu
.xml
.pipeline
.EventConsumer
;
54 * Event consumer which constructs DOM documents using the implementation
55 * in this package, using SAX2 events. This packages various backdoors
56 * into this DOM implementation, as needed to address DOM requirements
57 * that can't be met by strictly conforming implementations of DOM.
59 * <p> These requirements all relate to {@link DocumentType} nodes and
60 * features of that node type. These features are normally not used,
61 * because that interface only exposes a subset of the information found
62 * in DTDs. More, that subset does not include the most important typing
63 * information. For example, it excludes element content models and
64 * attribute typing. It does expose some entity management issues,
65 * although entity management doesn't relate to document typing.
67 * <p> Note that SAX2 does not expose the literal text of the DTD's
68 * internal subset, so it will not be present in DOM trees constructed
69 * using this API. (Though with a good SAX2 implementation, it could
70 * be partially recreated...)
72 * @author David Brownell
74 public class Consumer
extends DomConsumer
77 * Constructs an unconfigured event consumer,
78 * as a terminus in a SAX event pipeline.
80 // used by PipelineFactory [terminus]
84 super (DomDocument
.class);
85 setHandler (new Backdoor (this));
89 * Constructs an unconfigured event consumer,
90 * as a stage in a SAX event pipeline.
92 // used by PipelineFactory [filter]
93 public Consumer (EventConsumer next
)
96 super (DomDocument
.class, next
);
97 setHandler (new Backdoor (this));
101 * Implements the backdoors needed by DOM.
102 * All methods in this class use implementation-specific APIs that are
103 * implied by the DOM specification (needed to implement testable
104 * behavior) but which are excluded from the DOM specification.
106 public static class Backdoor
extends DomConsumer
.Handler
110 * @param consumer must have been initialized to use the
111 * {@link DomDocument} class (or a subclass) for
112 * constructing DOM trees
114 protected Backdoor (DomConsumer consumer
)
116 { super (consumer
); }
119 private DomDoctype
getDoctype ()
122 DomDocument doc
= (DomDocument
) getDocument ();
123 DocumentType dt
= doc
.getDoctype ();
126 throw new SAXException ("doctype missing!");
127 return (DomDoctype
) dt
;
130 // SAX2 "lexical" event
131 public void startDTD (String name
, String publicId
, String systemId
)
134 DomDocument doc
= (DomDocument
) getDocument ();
136 super.startDTD (name
, publicId
, systemId
);
137 // DOM L2 doctype creation model is bizarre
138 DomDoctype dt
= new DomDoctype (doc
, name
, publicId
, systemId
);
139 doc
.appendChild (dt
);
142 // SAX2 "lexical" event
143 public void endDTD ()
147 // DOM L2 has no way to make things readonly
148 getDoctype ().makeReadonly ();
152 public void notationDecl (
154 String publicId
, String systemId
155 ) throws SAXException
157 // DOM L2 can't create/save notation nodes
158 getDoctype ().declareNotation (name
, publicId
, systemId
);
162 public void unparsedEntityDecl (
164 String publicId
, String systemId
,
166 ) throws SAXException
168 // DOM L2 can't create/save entity nodes
169 getDoctype ().declareEntity (name
, publicId
, systemId
,
173 // SAX2 declaration event
174 public void internalEntityDecl (String name
, String value
)
177 // DOM L2 can't create/save entity nodes
178 // NOTE: this doesn't save the value as a child of this
179 // node, though it could realistically do so.
180 getDoctype ().declareEntity (name
, null, null, null);
183 // SAX2 declaration event
184 public void externalEntityDecl (
188 ) throws SAXException
190 // DOM L2 can't create/save entity nodes
191 // NOTE: DOM allows for these to have children, if
192 // they don't have unbound namespace references.
193 getDoctype ().declareEntity (name
, publicId
, systemId
, null);
197 public void startElement (
202 ) throws SAXException
206 super.startElement (uri
, localName
, qName
, atts
);
208 // might there be more work?
210 if (!top
.hasAttributes () || !(atts
instanceof Attributes2
))
213 // remember any attributes that got defaulted
214 DomNamedNodeMap map
= (DomNamedNodeMap
) top
.getAttributes ();
215 Attributes2 attrs
= (Attributes2
) atts
;
216 int length
= atts
.getLength ();
219 for (int i
= 0; i
< length
; i
++) {
220 if (attrs
.isSpecified (i
))
223 // value was defaulted.
224 String temp
= attrs
.getQName (i
);
227 if ("".equals (temp
))
228 attr
= (DomAttr
) map
.getNamedItemNS (attrs
.getURI (i
),
229 atts
.getLocalName (i
));
231 attr
= (DomAttr
) map
.getNamedItem (temp
);
233 // DOM L2 can't write this flag, only read it
234 attr
.setSpecified (false);
238 public void endElement (
242 ) throws SAXException
244 DomNode top
= (DomNode
) getTop ();
246 super.endElement (uri
, localName
, qName
);
249 protected Text
createText (
255 DomDocument doc
= (DomDocument
) getDocument ();
258 return doc
.createCDATASection (buf
, off
, len
);
260 return doc
.createTextNode (buf
, off
, len
);
263 public void elementDecl(String name
, String model
)
266 getDoctype().elementDecl(name
, model
);
269 public void attributeDecl (
275 ) throws SAXException
277 getDoctype().attributeDecl(ename
, aname
, type
, mode
, value
);
279 if (value == null && !"ID".equals (type))
282 DomDoctype.ElementInfo info;
284 info = getDoctype ().getElementInfo (ename);
286 info.setAttrDefault (aname, value);
287 if ("ID".equals (type))
288 info.setIdAttr (aname);
293 // force duplicate name checking off while we're
294 // using parser output (don't duplicate the work)
295 public void startDocument () throws SAXException
297 super.startDocument ();
299 DomDocument doc
= (DomDocument
) getDocument ();
300 doc
.setStrictErrorChecking(false);
301 doc
.setBuilding(true);
305 * Required by DOM Level 3 to report document parameters
307 public void xmlDecl(String version
,
310 String inputEncoding
)
313 super.xmlDecl(version
, encoding
, standalone
, inputEncoding
);
315 DomDocument doc
= (DomDocument
) getDocument();
316 doc
.setXmlEncoding(encoding
);
317 doc
.setInputEncoding(inputEncoding
);
320 public void endDocument ()
323 DomDocument doc
= (DomDocument
) getDocument ();
324 doc
.setStrictErrorChecking(true);
325 doc
.setBuilding(false);
327 DomDoctype doctype
= (DomDoctype
) doc
.getDoctype();
330 doctype
.makeReadonly();
332 super.endDocument ();
335 // these three methods collaborate to populate entity
336 // refs, marking contents readonly on end-of-entity
338 public boolean canPopulateEntityRefs ()
341 public void startEntity (String name
)
344 if (name
.charAt (0) == '%' || "[dtd]".equals (name
))
346 super.startEntity (name
);
348 DomNode top
= (DomNode
) getTop ();
350 if (top
.getNodeType () == Node
.ENTITY_REFERENCE_NODE
)
351 top
.readonly
= false;
354 public void endEntity (String name
)
357 if (name
.charAt (0) == '%' || "[dtd]".equals (name
))
359 DomNode top
= (DomNode
) getTop ();
361 if (top
.getNodeType () == Node
.ENTITY_REFERENCE_NODE
) {
365 super.endEntity (name
);