libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / xml / libxmlj / dom / GnomeNode.java
blob6f574ec29ddaaaabb5734e9d768bfc622643dd00
1 /* GnomeNode.java -
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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;
44 import java.util.Map;
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;
57 /**
58 * A DOM node implemented in libxml2.
60 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
62 class GnomeNode
63 implements Node, Comparable
66 /**
67 * Maps document pointers to a map of node pointers to node instances.
69 static Map instances;
71 /**
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,
79 final int type)
81 if (doc == null)
83 throw new NullPointerException("doc");
85 if (node == null)
87 throw new NullPointerException("node");
89 if (instances == null)
91 instances = new HashMap();
93 Map docNodes = (Map) instances.get(doc);
94 if (docNodes == null)
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
104 switch (type)
106 case ELEMENT_NODE:
107 nodeInstance = new GnomeElement(node);
108 break;
109 case ATTRIBUTE_NODE:
110 nodeInstance = new GnomeAttr(node);
111 break;
112 case TEXT_NODE:
113 nodeInstance = new GnomeText(node);
114 break;
115 case CDATA_SECTION_NODE:
116 nodeInstance = new GnomeCDATASection(node);
117 break;
118 case ENTITY_REFERENCE_NODE:
119 nodeInstance = new GnomeEntityReference(node);
120 break;
121 case ENTITY_NODE:
122 nodeInstance = new GnomeEntity(node);
123 break;
124 case PROCESSING_INSTRUCTION_NODE:
125 nodeInstance = new GnomeProcessingInstruction(node);
126 break;
127 case COMMENT_NODE:
128 nodeInstance = new GnomeComment(node);
129 break;
130 case DOCUMENT_NODE:
131 nodeInstance = new GnomeDocument(node);
132 break;
133 case DOCUMENT_TYPE_NODE:
134 nodeInstance = new GnomeDocumentType(node);
135 break;
136 case DOCUMENT_FRAGMENT_NODE:
137 nodeInstance = new GnomeDocumentFragment(node);
138 break;
139 case NOTATION_NODE:
140 nodeInstance = new GnomeNotation(node);
141 break;
142 default:
143 throw new IllegalArgumentException("Unknown node type: " + type);
145 docNodes.put(node, nodeInstance);
146 return 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)
157 return;
159 instances.remove(doc);
160 //System.out.println("Freed "+instances.remove(doc));
164 * xmlNodePtr
166 final Object id;
168 Map userData;
169 Map userDataHandlers;
171 GnomeNode(final Object id)
173 this.id = id;
176 public native String getNodeName();
178 public native String getNodeValue()
179 throws DOMException;
181 public native void setNodeValue(String nodeValue)
182 throws DOMException;
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)
209 throws DOMException
211 if (newChild instanceof StandaloneDocumentType)
213 DocumentType dt = (DocumentType) newChild;
214 newChild = ((GnomeDocument) getOwnerDocument())
215 .createDocumentType(dt.getName(), dt.getPublicId(),
216 dt.getSystemId());
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)
234 throws DOMException;
236 public Node replaceChild(Node newChild, Node oldChild)
237 throws DOMException
239 if (newChild instanceof StandaloneDocumentType)
241 DocumentType dt = (DocumentType) newChild;
242 newChild = ((GnomeDocument) getOwnerDocument())
243 .createDocumentType(dt.getName(), dt.getPublicId(),
244 dt.getSystemId());
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)
262 throws DOMException;
264 public Node removeChild(Node oldChild)
265 throws DOMException
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)
275 throws DOMException;
277 public Node appendChild(Node newChild)
278 throws DOMException
280 if (newChild instanceof StandaloneDocumentType)
282 DocumentType dt = (DocumentType) newChild;
283 newChild = ((GnomeDocument) getOwnerDocument())
284 .createDocumentType(dt.getName(), dt.getPublicId(),
285 dt.getSystemId());
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)
295 throws DOMException;
297 public native boolean hasChildNodes();
299 public Node cloneNode(boolean deep)
301 Node ret = xmljCloneNode(deep);
302 notifyUserDataHandlers(UserDataHandler.NODE_CLONED, this, ret);
303 return 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)
321 throws DOMException;
323 public native String getLocalName();
325 public native boolean hasAttributes();
327 public int hashCode()
329 return id.hashCode();
332 public boolean equals(Object other)
334 if (other == this)
336 return true;
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)
347 throws DOMException
349 return (short) compareTo(other);
352 public final int compareTo(Object other)
354 if (other instanceof GnomeNode)
356 return xmljCompareTo(other);
358 return 0;
361 private native int xmljCompareTo(Object other);
363 public String getTextContent()
364 throws DOMException
366 switch (getNodeType())
368 case ELEMENT_NODE:
369 case ATTRIBUTE_NODE:
370 case ENTITY_NODE:
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();
386 case TEXT_NODE:
387 case CDATA_SECTION_NODE:
388 case COMMENT_NODE:
389 case PROCESSING_INSTRUCTION_NODE:
390 return getNodeValue();
391 default:
392 return null;
396 public void setTextContent(String textContent)
397 throws DOMException
399 switch (getNodeType())
401 case ENTITY_REFERENCE_NODE:
402 // entity references are read only
403 throw new GnomeDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
404 null);
405 case ELEMENT_NODE:
406 case ATTRIBUTE_NODE:
407 case ENTITY_NODE:
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);
414 removeChild(child);
416 if (textContent != null)
418 Text text = getOwnerDocument().createTextNode(textContent);
419 appendChild(text);
421 break;
422 case TEXT_NODE:
423 case CDATA_SECTION_NODE:
424 case COMMENT_NODE:
425 case PROCESSING_INSTRUCTION_NODE:
426 setNodeValue(textContent);
427 break;
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)
452 // TODO handler
453 if (userData == null)
455 userData = new HashMap();
457 if (handler != null)
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)
472 return 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());
497 buffer.append("]");
498 return buffer.toString();