2 Copyright (C) 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. */
38 package gnu
.xml
.libxmlj
.dom
;
40 import gnu
.java
.lang
.CPStringBuilder
;
42 import java
.util
.HashMap
;
43 import java
.util
.Iterator
;
46 import org
.w3c
.dom
.Document
;
47 import org
.w3c
.dom
.DocumentType
;
48 import org
.w3c
.dom
.DOMException
;
49 import org
.w3c
.dom
.NamedNodeMap
;
50 import org
.w3c
.dom
.Node
;
51 import org
.w3c
.dom
.NodeList
;
52 import org
.w3c
.dom
.Text
;
53 import org
.w3c
.dom
.UserDataHandler
;
55 import gnu
.xml
.libxmlj
.util
.StandaloneDocumentType
;
58 * A DOM node implemented in libxml2.
60 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
63 implements Node
, Comparable
67 * Maps document pointers to a map of node pointers to node instances.
72 * Retrieves the node instance for the specified node pointer.
73 * This creates a new instance and adds it to the cache if required.
74 * @param doc the document pointer
75 * @param node the node pointer
76 * @param type the node type
78 static GnomeNode
newInstance(final Object doc
, final Object node
,
83 throw new NullPointerException("doc");
87 throw new NullPointerException("node");
89 if (instances
== null)
91 instances
= new HashMap();
93 Map docNodes
= (Map
) instances
.get(doc
);
96 docNodes
= new HashMap(1024); // TODO review optimal initial capacity
97 instances
.put(doc
, docNodes
);
99 GnomeNode nodeInstance
= (GnomeNode
) docNodes
.get(node
);
100 if (nodeInstance
!= null)
102 return nodeInstance
; // Return cached version
107 nodeInstance
= new GnomeElement(node
);
110 nodeInstance
= new GnomeAttr(node
);
113 nodeInstance
= new GnomeText(node
);
115 case CDATA_SECTION_NODE
:
116 nodeInstance
= new GnomeCDATASection(node
);
118 case ENTITY_REFERENCE_NODE
:
119 nodeInstance
= new GnomeEntityReference(node
);
122 nodeInstance
= new GnomeEntity(node
);
124 case PROCESSING_INSTRUCTION_NODE
:
125 nodeInstance
= new GnomeProcessingInstruction(node
);
128 nodeInstance
= new GnomeComment(node
);
131 nodeInstance
= new GnomeDocument(node
);
133 case DOCUMENT_TYPE_NODE
:
134 nodeInstance
= new GnomeDocumentType(node
);
136 case DOCUMENT_FRAGMENT_NODE
:
137 nodeInstance
= new GnomeDocumentFragment(node
);
140 nodeInstance
= new GnomeNotation(node
);
143 throw new IllegalArgumentException("Unknown node type: " + type
);
145 docNodes
.put(node
, nodeInstance
);
150 * Frees the specified document.
151 * This removes all its nodes from the cache.
153 static void freeDocument(final Object doc
)
155 if (instances
== null || doc
== null)
159 instances
.remove(doc
);
160 //System.out.println("Freed "+instances.remove(doc));
169 Map userDataHandlers
;
171 GnomeNode(final Object id
)
176 public native String
getNodeName();
178 public native String
getNodeValue()
181 public native void setNodeValue(String nodeValue
)
184 public native short getNodeType();
186 public native Node
getParentNode();
188 public NodeList
getChildNodes()
190 return new GnomeNodeList(id
);
193 public native Node
getFirstChild();
195 public native Node
getLastChild();
197 public native Node
getPreviousSibling();
199 public native Node
getNextSibling();
201 public NamedNodeMap
getAttributes()
203 return new GnomeNamedNodeMap(id
, 0);
206 public native Document
getOwnerDocument();
208 public Node
insertBefore(Node newChild
, Node refChild
)
211 if (newChild
instanceof StandaloneDocumentType
)
213 DocumentType dt
= (DocumentType
) newChild
;
214 newChild
= ((GnomeDocument
) getOwnerDocument())
215 .createDocumentType(dt
.getName(), dt
.getPublicId(),
218 if (newChild
== null)
220 throw new GnomeDOMException(DOMException
.NOT_FOUND_ERR
, null);
222 if (!(newChild
instanceof GnomeNode
))
224 throw new GnomeDOMException(DOMException
.WRONG_DOCUMENT_ERR
, null);
226 if (refChild
== null || !(refChild
instanceof GnomeNode
))
228 throw new GnomeDOMException(DOMException
.NOT_FOUND_ERR
, null);
230 return xmljInsertBefore(newChild
, refChild
);
233 private native Node
xmljInsertBefore(Node newChild
, Node refChild
)
236 public Node
replaceChild(Node newChild
, Node oldChild
)
239 if (newChild
instanceof StandaloneDocumentType
)
241 DocumentType dt
= (DocumentType
) newChild
;
242 newChild
= ((GnomeDocument
) getOwnerDocument())
243 .createDocumentType(dt
.getName(), dt
.getPublicId(),
246 if (newChild
== null)
248 throw new GnomeDOMException(DOMException
.NOT_FOUND_ERR
, null);
250 if (!(newChild
instanceof GnomeNode
))
252 throw new GnomeDOMException(DOMException
.WRONG_DOCUMENT_ERR
, newChild
.toString());
254 if (oldChild
== null || !(oldChild
instanceof GnomeNode
))
256 throw new GnomeDOMException(DOMException
.NOT_FOUND_ERR
, null);
258 return xmljReplaceChild(newChild
, oldChild
);
261 private native Node
xmljReplaceChild(Node newChild
, Node oldChild
)
264 public Node
removeChild(Node oldChild
)
267 if (!(oldChild
instanceof GnomeNode
))
269 throw new GnomeDOMException(DOMException
.WRONG_DOCUMENT_ERR
, null);
271 return xmljRemoveChild(oldChild
);
274 private native Node
xmljRemoveChild(Node oldChild
)
277 public Node
appendChild(Node newChild
)
280 if (newChild
instanceof StandaloneDocumentType
)
282 DocumentType dt
= (DocumentType
) newChild
;
283 newChild
= ((GnomeDocument
) getOwnerDocument())
284 .createDocumentType(dt
.getName(), dt
.getPublicId(),
287 if (!(newChild
instanceof GnomeNode
))
289 throw new GnomeDOMException(DOMException
.WRONG_DOCUMENT_ERR
, null);
291 return xmljAppendChild(newChild
);
294 private native Node
xmljAppendChild(Node newChild
)
297 public native boolean hasChildNodes();
299 public Node
cloneNode(boolean deep
)
301 Node ret
= xmljCloneNode(deep
);
302 notifyUserDataHandlers(UserDataHandler
.NODE_CLONED
, this, ret
);
306 private native Node
xmljCloneNode(boolean deep
);
308 public native void normalize();
310 public boolean isSupported(String feature
, String version
)
312 return getOwnerDocument().getImplementation()
313 .hasFeature(feature
, version
);
316 public native String
getNamespaceURI();
318 public native String
getPrefix();
320 public native void setPrefix(String prefix
)
323 public native String
getLocalName();
325 public native boolean hasAttributes();
327 public int hashCode()
329 return id
.hashCode();
332 public boolean equals(Object other
)
338 return (other
instanceof GnomeNode
&&
339 ((GnomeNode
) other
).id
== id
);
342 // DOM Level 3 methods
344 public native String
getBaseURI();
346 public short compareDocumentPosition(Node other
)
349 return (short) compareTo(other
);
352 public final int compareTo(Object other
)
354 if (other
instanceof GnomeNode
)
356 return xmljCompareTo(other
);
361 private native int xmljCompareTo(Object other
);
363 public String
getTextContent()
366 switch (getNodeType())
371 case ENTITY_REFERENCE_NODE
:
372 case DOCUMENT_FRAGMENT_NODE
:
373 CPStringBuilder buffer
= new CPStringBuilder();
374 NodeList children
= getChildNodes();
375 int len
= children
.getLength();
376 for (int i
= 0; i
< len
; i
++)
378 Node child
= children
.item(i
);
379 String textContent
= child
.getTextContent();
380 if (textContent
!= null)
382 buffer
.append(textContent
);
385 return buffer
.toString();
387 case CDATA_SECTION_NODE
:
389 case PROCESSING_INSTRUCTION_NODE
:
390 return getNodeValue();
396 public void setTextContent(String textContent
)
399 switch (getNodeType())
401 case ENTITY_REFERENCE_NODE
:
402 // entity references are read only
403 throw new GnomeDOMException(DOMException
.NO_MODIFICATION_ALLOWED_ERR
,
408 case DOCUMENT_FRAGMENT_NODE
:
409 NodeList children
= getChildNodes();
410 int len
= children
.getLength();
411 for (int i
= 0; i
< len
; i
++)
413 Node child
= children
.item(i
);
416 if (textContent
!= null)
418 Text text
= getOwnerDocument().createTextNode(textContent
);
423 case CDATA_SECTION_NODE
:
425 case PROCESSING_INSTRUCTION_NODE
:
426 setNodeValue(textContent
);
431 public boolean isSameNode(Node other
)
433 return equals(other
);
436 public native String
lookupPrefix(String namespaceURI
);
438 public native boolean isDefaultNamespace(String namespaceURI
);
440 public native String
lookupNamespaceURI(String prefix
);
442 public native boolean isEqualNode(Node arg
);
444 public Object
getFeature(String feature
, String version
)
446 return getOwnerDocument().getImplementation()
447 .getFeature(feature
, version
);
450 public Object
setUserData(String key
, Object data
, UserDataHandler handler
)
453 if (userData
== null)
455 userData
= new HashMap();
459 if (userDataHandlers
== null)
461 userDataHandlers
= new HashMap();
463 userDataHandlers
.put(key
, handler
);
465 return userData
.put(key
, data
);
468 public Object
getUserData(String key
)
470 if (userData
== null)
474 return userData
.get(key
);
477 void notifyUserDataHandlers(short op
, Node src
, Node dst
)
479 if (userDataHandlers
!= null)
481 for (Iterator i
= userDataHandlers
.entrySet().iterator(); i
.hasNext(); )
483 Map
.Entry entry
= (Map
.Entry
) i
.next();
484 String key
= (String
) entry
.getKey();
485 UserDataHandler handler
= (UserDataHandler
) entry
.getValue();
486 Object data
= userData
.get(key
);
487 handler
.handle(op
, key
, data
, src
, dst
);
492 public String
toString()
494 CPStringBuilder buffer
= new CPStringBuilder(getClass().getName());
495 buffer
.append("[nodeName=");
496 buffer
.append(getNodeName());
498 return buffer
.toString();