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., 51 Franklin Street, Fifth Floor, 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);
304 public void endDocument ()
307 DomDocument doc
= (DomDocument
) getDocument ();
308 doc
.setStrictErrorChecking(true);
309 doc
.setBuilding(false);
311 DomDoctype doctype
= (DomDoctype
) doc
.getDoctype();
314 doctype
.makeReadonly();
316 super.endDocument ();
319 // these three methods collaborate to populate entity
320 // refs, marking contents readonly on end-of-entity
322 public boolean canPopulateEntityRefs ()
325 public void startEntity (String name
)
328 if (name
.charAt (0) == '%' || "[dtd]".equals (name
))
330 super.startEntity (name
);
332 DomNode top
= (DomNode
) getTop ();
334 if (top
.getNodeType () == Node
.ENTITY_REFERENCE_NODE
)
335 top
.readonly
= false;
338 public void endEntity (String name
)
341 if (name
.charAt (0) == '%' || "[dtd]".equals (name
))
343 DomNode top
= (DomNode
) getTop ();
345 if (top
.getNodeType () == Node
.ENTITY_REFERENCE_NODE
) {
349 super.endEntity (name
);