blob: d5ab7a52b41f0ac95d971217660682896def5c65 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package javax.imageio.metadata;
19
20import java.util.ArrayList;
21import java.util.List;
22
23import org.w3c.dom.Attr;
24import org.w3c.dom.DOMException;
25import org.w3c.dom.Document;
26import org.w3c.dom.Element;
27import org.w3c.dom.NamedNodeMap;
28import org.w3c.dom.Node;
29import org.w3c.dom.NodeList;
30//???AWT
31//import org.w3c.dom.TypeInfo;
32//import org.w3c.dom.UserDataHandler;
33
34/**
35 * The Class IIOMetadataNode represents a node of the
36 * (DOM-style) metadata tree.
37 */
38public class IIOMetadataNode implements Element, NodeList {
39
40 /** The node name. */
41 private String nodeName;
42
43 /** The node value. */
44 private String nodeValue;
45
46 /** The attributes. */
47 private IIOMetadataNodeList attrs = new IIOMetadataNodeList(new ArrayList<IIOMetadataNode>());
48
49 /** The parent node. */
50 private IIOMetadataNode parent;
51
52 /** The first child node. */
53 private IIOMetadataNode firstChild;
54
55 /** The last child node. */
56 private IIOMetadataNode lastChild;
57
58 /** The previous sibling. */
59 private IIOMetadataNode previousSibling;
60
61 /** The next sibling. */
62 private IIOMetadataNode nextSibling;
63
64 /** The number of children. */
65 private int nChildren;
66
67 /** The user object associated with this node. */
68 private Object userObject;
69
70 /** The text content of this node. */
71 private String textContent;
72
73 /**
74 * Instantiates a new empty node.
75 */
76 public IIOMetadataNode() {
77 }
78
79 /**
80 * Instantiates a new empty node with the specified name.
81 *
82 * @param nodeName the node name
83 */
84 public IIOMetadataNode(String nodeName) {
85 this.nodeName = nodeName;
86 }
87
88 /**
89 * Instantiates a new IIOMetadataNode with the specified
90 * name and value.
91 *
92 * @param nodeName the node name
93 * @param nodeValue the node value
94 */
95 private IIOMetadataNode(String nodeName, String nodeValue) {
96 this.nodeName = nodeName;
97 this.nodeValue = nodeValue;
98 }
99
100 public String getTagName() {
101 return nodeName;
102 }
103
104 public String getAttribute(String name) {
105 Attr attrNode = (Attr) attrs.getNamedItem(name);
106 return (attrNode == null) ? "" : attrNode.getValue();
107 }
108
109 public void setAttribute(String name, String value) throws DOMException {
110 Attr attr = (Attr) attrs.getNamedItem(name);
111 if (attr != null) {
112 attr.setValue(value);
113 } else {
114 attrs.list.add(new IIOMetadataAttr(name, value, this));
115 }
116 }
117
118 public void removeAttribute(String name) throws DOMException {
119 IIOMetadataAttr attr = (IIOMetadataAttr) attrs.getNamedItem(name);
120 if (attr != null) {
121 attr.setOwnerElement(null);
122 attrs.list.remove(attr);
123 }
124 }
125
126 public Attr getAttributeNode(String name) {
127 return (Attr) attrs.getNamedItem(name);
128 }
129
130 public Attr setAttributeNode(Attr newAttr) throws DOMException {
131 // Check if this attribute is already in use.
132 Element owner = newAttr.getOwnerElement();
133 if (owner != null) {
134 if (owner == this) { // Replacing an attribute node by itself has no effect
135 return null;
136 } else {
137 throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, "Attribute is already in use");
138 }
139 }
140
141 String name = newAttr.getName();
142 Attr oldAttr = getAttributeNode(name);
143 if (oldAttr != null) {
144 removeAttributeNode(oldAttr);
145 }
146
147 IIOMetadataAttr iioAttr;
148 if (newAttr instanceof IIOMetadataAttr) {
149 iioAttr = (IIOMetadataAttr) newAttr;
150 iioAttr.setOwnerElement(this);
151 } else {
152 iioAttr = new IIOMetadataAttr(name, newAttr.getValue(), this);
153 }
154
155 attrs.list.add(iioAttr);
156
157 return oldAttr;
158 }
159
160 public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
161 if (!attrs.list.remove(oldAttr)) { // Not found
162 throw new DOMException(DOMException.NOT_FOUND_ERR, "No such attribute!");
163 }
164
165 ((IIOMetadataAttr)oldAttr).setOwnerElement(null);
166
167 return oldAttr;
168 }
169
170 public NodeList getElementsByTagName(String name) {
171 ArrayList<IIOMetadataNode> nodes = new ArrayList<IIOMetadataNode>();
172
173 // Non-recursive tree walk
174 Node pos = this;
175
176 while (pos != null) {
177 if (pos.getNodeName().equals(name)) {
178 nodes.add((IIOMetadataNode)pos);
179 }
180
181 Node nextNode = pos.getFirstChild();
182
183 while (nextNode == null) {
184 if (pos == this) {
185 break;
186 }
187
188 nextNode = pos.getNextSibling();
189
190 if (nextNode == null) {
191 pos = pos.getParentNode();
192
193 if (pos == null || pos == this) {
194 nextNode = null;
195 break;
196 }
197 }
198 }
199 pos = nextNode;
200 }
201
202 return new IIOMetadataNodeList(nodes);
203 }
204
205 public String getAttributeNS(String namespaceURI, String localName) throws DOMException {
206 return getAttribute(localName);
207 }
208
209 public void setAttributeNS(String namespaceURI, String qualifiedName, String value) throws DOMException {
210 setAttribute(qualifiedName, value);
211 }
212
213 public void removeAttributeNS(String namespaceURI, String localName) throws DOMException {
214 removeAttribute(localName);
215 }
216
217 public Attr getAttributeNodeNS(String namespaceURI, String localName) throws DOMException {
218 return getAttributeNode(localName);
219 }
220
221 public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
222 return setAttributeNode(newAttr);
223 }
224
225 public NodeList getElementsByTagNameNS(String namespaceURI, String localName) throws DOMException {
226 return getElementsByTagName(localName);
227 }
228
229 public boolean hasAttribute(String name) {
230 return attrs.getNamedItem(name) != null;
231 }
232
233 public boolean hasAttributeNS(String namespaceURI, String localName) throws DOMException {
234 return hasAttribute(localName);
235 }
236
237 //???AWT
238 /*
239 public TypeInfo getSchemaTypeInfo() {
240 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
241 }*/
242
243 public void setIdAttribute(String name, boolean isId) throws DOMException {
244 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
245 }
246
247 public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) throws DOMException {
248 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
249 }
250
251 public void setIdAttributeNode(Attr idAttr, boolean isId) throws DOMException {
252 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
253 }
254
255 public String getNodeName() {
256 return nodeName;
257 }
258
259 public String getNodeValue() throws DOMException {
260 return nodeValue;
261 }
262
263 public void setNodeValue(String nodeValue) throws DOMException {
264 this.nodeValue = nodeValue;
265 }
266
267 public short getNodeType() {
268 return ELEMENT_NODE;
269 }
270
271 public Node getParentNode() {
272 return parent;
273 }
274
275 public NodeList getChildNodes() {
276 return this;
277 }
278
279 public Node getFirstChild() {
280 return firstChild;
281 }
282
283 public Node getLastChild() {
284 return lastChild;
285 }
286
287 public Node getPreviousSibling() {
288 return previousSibling;
289 }
290
291 public Node getNextSibling() {
292 return nextSibling;
293 }
294
295 public NamedNodeMap getAttributes() {
296 return attrs;
297 }
298
299 public Document getOwnerDocument() {
300 return null;
301 }
302
303 public Node insertBefore(Node newChild, Node refChild) throws DOMException {
304 if (newChild == null) {
305 throw new IllegalArgumentException("newChild == null!");
306 }
307
308 IIOMetadataNode newIIOChild = (IIOMetadataNode) newChild;
309 IIOMetadataNode refIIOChild = (IIOMetadataNode) refChild;
310
311 newIIOChild.parent = this;
312
313 if (refIIOChild == null) {
314 newIIOChild.nextSibling = null;
315 newIIOChild.previousSibling = lastChild;
316
317 // Fix this node
318 lastChild = newIIOChild;
319 if (firstChild == null) {
320 firstChild = newIIOChild;
321 }
322 } else {
323 newIIOChild.nextSibling = refIIOChild;
324 newIIOChild.previousSibling = refIIOChild.previousSibling;
325
326 // Fix this node
327 if (firstChild == refIIOChild) {
328 firstChild = newIIOChild;
329 }
330
331 // Fix next node
332 if (refIIOChild != null) {
333 refIIOChild.previousSibling = newIIOChild;
334 }
335 }
336
337 // Fix prev node
338 if (newIIOChild.previousSibling != null) {
339 newIIOChild.previousSibling.nextSibling = newIIOChild;
340 }
341
342 nChildren++;
343
344 return newIIOChild;
345 }
346
347 public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
348 if (newChild == null) {
349 throw new IllegalArgumentException("newChild == null!");
350 }
351
352 IIOMetadataNode newIIOChild = (IIOMetadataNode) newChild;
353 IIOMetadataNode oldIIOChild = (IIOMetadataNode) oldChild;
354
355 IIOMetadataNode next = oldIIOChild.nextSibling;
356 IIOMetadataNode previous = oldIIOChild.previousSibling;
357
358 // Fix new node
359 newIIOChild.parent = this;
360 newIIOChild.nextSibling = next;
361 newIIOChild.previousSibling = previous;
362
363 // Fix this node
364 if (lastChild == oldIIOChild) {
365 lastChild = newIIOChild;
366 }
367 if (firstChild == oldIIOChild) {
368 firstChild = newIIOChild;
369 }
370
371 // Fix siblings
372 if (next != null) {
373 next.previousSibling = newIIOChild;
374 }
375 if (previous != null) {
376 previous.nextSibling = newIIOChild;
377 }
378
379 // Fix old child
380 oldIIOChild.parent = null;
381 oldIIOChild.nextSibling = next;
382 oldIIOChild.previousSibling = previous;
383
384 return oldIIOChild;
385 }
386
387 public Node removeChild(Node oldChild) throws DOMException {
388 if (oldChild == null) {
389 throw new IllegalArgumentException("oldChild == null!");
390 }
391
392 IIOMetadataNode oldIIOChild = (IIOMetadataNode) oldChild;
393
394 // Fix next and previous
395 IIOMetadataNode previous = oldIIOChild.previousSibling;
396 IIOMetadataNode next = oldIIOChild.nextSibling;
397
398 if (previous != null) {
399 previous.nextSibling = next;
400 }
401 if (next != null) {
402 next.previousSibling = previous;
403 }
404
405 // Fix this node
406 if (lastChild == oldIIOChild) {
407 lastChild = previous;
408 }
409 if (firstChild == oldIIOChild) {
410 firstChild = next;
411 }
412 nChildren--;
413
414 // Fix old child
415 oldIIOChild.parent = null;
416 oldIIOChild.previousSibling = null;
417 oldIIOChild.nextSibling = null;
418
419 return oldIIOChild;
420 }
421
422 public Node appendChild(Node newChild) throws DOMException {
423 return insertBefore(newChild, null);
424 }
425
426 public boolean hasChildNodes() {
427 return nChildren != 0;
428 }
429
430 public Node cloneNode(boolean deep) {
431 IIOMetadataNode cloned = new IIOMetadataNode(nodeName);
432 cloned.setUserObject(getUserObject());
433
434 if (deep) { // Clone recursively
435 IIOMetadataNode c = firstChild;
436 while (c != null) {
437 cloned.insertBefore(c.cloneNode(true), null);
438 c = c.nextSibling;
439 }
440 }
441
442 return cloned; //To change body of implemented methods use File | Settings | File Templates.
443 }
444
445 public void normalize() {
446 // Do nothing
447 }
448
449 public boolean isSupported(String feature, String version) {
450 return false;
451 }
452
453 public String getNamespaceURI() {
454 return null;
455 }
456
457 public String getPrefix() {
458 return null;
459 }
460
461 public void setPrefix(String prefix) throws DOMException {
462 // Do nothing
463 }
464
465 public String getLocalName() {
466 return nodeName;
467 }
468
469 public boolean hasAttributes() {
470 return attrs.list.size() > 0;
471 }
472
473 public String getBaseURI() {
474 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
475 }
476
477 public short compareDocumentPosition(Node other) throws DOMException {
478 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
479 }
480
481 public String getTextContent() throws DOMException {
482 return textContent;
483 }
484
485 public void setTextContent(String textContent) throws DOMException {
486 this.textContent = textContent;
487 }
488
489 public boolean isSameNode(Node other) {
490 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
491 }
492
493 public String lookupPrefix(String namespaceURI) {
494 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
495 }
496
497 public boolean isDefaultNamespace(String namespaceURI) {
498 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
499 }
500
501 public String lookupNamespaceURI(String prefix) {
502 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
503 }
504
505 public boolean isEqualNode(Node arg) {
506 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
507 }
508
509 public Object getFeature(String feature, String version) {
510 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
511 }
512
513 //???AWT
514 /*
515 public Object setUserData(String key, Object data, UserDataHandler handler) {
516 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
517 }*/
518
519 public Object getUserData(String key) {
520 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
521 }
522
523 public Node item(int index) {
524 if (index < 0 || index >= nChildren) {
525 return null;
526 }
527
528 Node n;
529 for (n = getFirstChild(); index > 0; index--) {
530 n = n.getNextSibling();
531 }
532
533 return n;
534 }
535
536 public int getLength() {
537 return nChildren;
538 }
539
540 /**
541 * Gets the user object associated with this node.
542 *
543 * @return the user object associated with this node
544 */
545 public Object getUserObject() {
546 return userObject;
547 }
548
549 /**
550 * Sets the user object associated with this node.
551 *
552 * @param userObject the new user object associated with this node
553 */
554 public void setUserObject(Object userObject) {
555 this.userObject = userObject;
556 }
557
558 /**
559 * The Class IIOMetadataAttr.
560 */
561 private class IIOMetadataAttr extends IIOMetadataNode implements Attr {
562
563 /** The owner element. */
564 private Element ownerElement;
565
566 /**
567 * Instantiates a new iIO metadata attr.
568 *
569 * @param name the name
570 * @param value the value
571 * @param owner the owner
572 */
573 public IIOMetadataAttr(String name, String value, Element owner) {
574 super(name, value);
575 this.ownerElement = owner;
576 }
577
578 public String getName() {
579 return getNodeName();
580 }
581
582 public boolean getSpecified() {
583 return true;
584 }
585
586 public String getValue() {
587 return nodeValue;
588 }
589
590 public void setValue(String value) throws DOMException {
591 nodeValue = value;
592 }
593
594 public Element getOwnerElement() {
595 return ownerElement;
596 }
597
598 /**
599 * Sets the owner element.
600 *
601 * @param ownerElement the new owner element
602 */
603 public void setOwnerElement(Element ownerElement) {
604 this.ownerElement = ownerElement;
605 }
606
607 public boolean isId() {
608 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Method not supported");
609 }
610
611 @Override
612 public short getNodeType() {
613 return ATTRIBUTE_NODE;
614 }
615 }
616
617 /**
618 * The Class IIOMetadataNodeList.
619 */
620 private class IIOMetadataNodeList implements NodeList, NamedNodeMap {
621
622 /** The list. */
623 private List<IIOMetadataNode> list;
624
625 /**
626 * Instantiates a new iIO metadata node list.
627 *
628 * @param list the list
629 */
630 IIOMetadataNodeList(List<IIOMetadataNode> list) {
631 this.list = list;
632 }
633
634 public Node item(int index) {
635 try {
636 return list.get(index);
637 } catch (IndexOutOfBoundsException e) {
638 return null;
639 }
640 }
641
642 public int getLength() {
643 return list.size();
644 }
645
646 public Node getNamedItem(String name) {
647 for(IIOMetadataNode node:list) {
648 if (name.equals(node.getNodeName())) {
649 return node;
650 }
651 }
652 return null;
653 }
654
655 public Node setNamedItem(Node arg) throws DOMException {
656 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
657 }
658
659 public Node removeNamedItem(String name) throws DOMException {
660 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
661 }
662
663 public Node getNamedItemNS(String namespaceURI, String localName) throws DOMException {
664 return getNamedItem(localName);
665 }
666
667 public Node setNamedItemNS(Node arg) throws DOMException {
668 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
669 }
670
671 public Node removeNamedItemNS(String namespaceURI, String localName) throws DOMException {
672 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, "This NamedNodeMap is read-only!");
673 }
674 }
675}