001    /* IIOMetadataNode.java --
002       Copyright (C) 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.imageio.metadata;
040    
041    import java.util.ArrayList;
042    import java.util.HashMap;
043    import java.util.Iterator;
044    import java.util.List;
045    
046    import org.w3c.dom.Attr;
047    import org.w3c.dom.DOMException;
048    import org.w3c.dom.Document;
049    import org.w3c.dom.Element;
050    import org.w3c.dom.NamedNodeMap;
051    import org.w3c.dom.Node;
052    import org.w3c.dom.NodeList;
053    import org.w3c.dom.TypeInfo;
054    import org.w3c.dom.UserDataHandler;
055    import javax.imageio.metadata.IIOMetadataFormatImpl.IIOMetadataNodeAttr;
056    
057    public class IIOMetadataNode
058      implements Element, NodeList
059    {
060      private String name;
061      private HashMap attrs = new HashMap();
062      private List children = new ArrayList();
063      private IIOMetadataNode parent;
064      private Object obj;
065    
066      /**
067       * Simple NamedNodeMap class for IIOMetadataNode.
068       *
069       * @author jlquinn
070       */
071      private class IIONamedNodeMap implements NamedNodeMap
072      {
073        HashMap attrs;
074    
075        /**
076         * @param attrs
077         * @param node
078         */
079        public IIONamedNodeMap(HashMap attrs)
080        {
081          this.attrs = attrs;
082        }
083    
084        /* (non-Javadoc)
085         * @see org.w3c.dom.NamedNodeMap#getNamedItem(java.lang.String)
086         */
087        public Node getNamedItem(String name)
088        {
089          return (Node)attrs.get(name);
090        }
091    
092        /* (non-Javadoc)
093         * @see org.w3c.dom.NamedNodeMap#setNamedItem(org.w3c.dom.Node)
094         */
095        public Node setNamedItem(Node arg) throws DOMException
096        {
097          if (arg instanceof IIOMetadataNodeAttr)
098            {
099              IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr) arg;
100              // The only code that can successfully do this is in this package.
101              if (attr.owner != null)
102                throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, "");
103              return (Node)attrs.put(attr.name, attr);
104            }
105          // Anything else gets treated as an invalid op.
106          throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, "");
107        }
108    
109        /* (non-Javadoc)
110         * @see org.w3c.dom.NamedNodeMap#removeNamedItem(java.lang.String)
111         */
112        public Node removeNamedItem(String name) throws DOMException
113        {
114          return (Node)attrs.remove(name);
115        }
116    
117        /* (non-Javadoc)
118         * @see org.w3c.dom.NamedNodeMap#item(int)
119         */
120        public Node item(int index)
121        {
122          return (Node)attrs.values().toArray()[index];
123        }
124    
125        /* (non-Javadoc)
126         * @see org.w3c.dom.NamedNodeMap#getLength()
127         */
128        public int getLength()
129        {
130          return attrs.size();
131        }
132    
133        /* (non-Javadoc)
134         * @see org.w3c.dom.NamedNodeMap#getNamedItemNS(java.lang.String, java.lang.String)
135         */
136        public Node getNamedItemNS(String namespaceURI, String localName)
137        {
138          return getNamedItem(localName);
139        }
140    
141        /* (non-Javadoc)
142         * @see org.w3c.dom.NamedNodeMap#setNamedItemNS(org.w3c.dom.Node)
143         */
144        public Node setNamedItemNS(Node arg) throws DOMException
145        {
146          return setNamedItem(arg);
147        }
148    
149        /* (non-Javadoc)
150         * @see org.w3c.dom.NamedNodeMap#removeNamedItemNS(java.lang.String, java.lang.String)
151         */
152        public Node removeNamedItemNS(String namespaceURI, String localName)
153          throws DOMException
154        {
155          return removeNamedItem(localName);
156        }
157      }
158    
159      /**
160       * Simple NodeList implementation for IIOMetadataNode.
161       *
162       * @author jlquinn
163       *
164       */
165      private class IIONodeList implements NodeList
166      {
167        List children = new ArrayList();
168    
169        /* (non-Javadoc)
170         * @see org.w3c.dom.NodeList#item(int)
171         */
172        public Node item(int index)
173        {
174          return (index < children.size()) ? (Node)children.get(index) : null;
175        }
176    
177        /* (non-Javadoc)
178         * @see org.w3c.dom.NodeList#getLength()
179         */
180        public int getLength()
181        {
182          return children.size();
183        }
184      }
185    
186      public IIOMetadataNode()
187      {
188        // Do nothing here.
189      }
190    
191      public IIOMetadataNode(String nodename)
192      {
193        name = nodename;
194      }
195    
196      public Object getUserObject()
197      {
198        return obj;
199      }
200    
201      public void setUserObject(Object o)
202      {
203        obj = o;
204      }
205    
206      public short compareDocumentPosition(Node other)
207        throws DOMException
208      {
209        return Element.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
210      }
211    
212      /* (non-Javadoc)
213       * @see org.w3c.dom.Element#getAttribute(java.lang.String)
214       */
215      public String getAttribute(String name)
216      {
217        Attr anode = (Attr) attrs.get(name);
218        return anode != null ? anode.getValue() : null;
219      }
220    
221      /* (non-Javadoc)
222       * @see org.w3c.dom.Element#getAttributeNode(java.lang.String)
223       */
224      public Attr getAttributeNode(String name)
225      {
226        String val = getAttribute(name);
227        if (val != null)
228          return new IIOMetadataNodeAttr(this, name, val);
229        return null;
230      }
231    
232      /* (non-Javadoc)
233       * @see org.w3c.dom.Element#getAttributeNodeNS(java.lang.String, java.lang.String)
234       */
235      public Attr getAttributeNodeNS(String namespaceURI, String localName)
236      {
237        return getAttributeNode(localName);
238      }
239    
240      /* (non-Javadoc)
241       * @see org.w3c.dom.Element#getAttributeNS(java.lang.String, java.lang.String)
242       */
243      public String getAttributeNS(String namespaceURI, String localName)
244      {
245        return getAttribute(localName);
246      }
247    
248      public String getBaseURI()
249      {
250        return null;
251      }
252    
253      // Recursive function for assembling a node list.
254      private void getElementsRecurse(IIONodeList list, String name)
255      {
256        for (int i=0; i < children.size(); i++)
257        {
258          if (((Node)children.get(i)).getNodeName().equals(name))
259            list.children.add(children.get(i));
260          getElementsRecurse(list, name);
261        }
262      }
263    
264      /* (non-Javadoc)
265       * @see org.w3c.dom.Element#getElementsByTagName(java.lang.String)
266       */
267      public NodeList getElementsByTagName(String name)
268      {
269        IIONodeList list = new IIONodeList();
270        getElementsRecurse(list, name);
271        return list;
272      }
273    
274      /* (non-Javadoc)
275       * @see org.w3c.dom.Element#getElementsByTagNameNS(java.lang.String, java.lang.String)
276       */
277      public NodeList getElementsByTagNameNS(String namespaceURI, String localName)
278      {
279        IIONodeList list = new IIONodeList();
280        getElementsRecurse(list, name);
281        return list;
282      }
283    
284      /* (non-Javadoc)
285       * @see org.w3c.dom.Element#getTagName()
286       */
287      public String getTagName()
288      {
289        return name;
290      }
291    
292      /* (non-Javadoc)
293       * @see org.w3c.dom.Element#hasAttribute(java.lang.String)
294       */
295      public boolean hasAttribute(String name)
296      {
297        return attrs.containsKey(name);
298      }
299    
300      /* (non-Javadoc)
301       * @see org.w3c.dom.Element#hasAttributeNS(java.lang.String, java.lang.String)
302       */
303      public boolean hasAttributeNS(String namespaceURI, String localName)
304      {
305        return attrs.containsKey(localName);
306      }
307    
308      /* (non-Javadoc)
309       * @see org.w3c.dom.Element#removeAttribute(java.lang.String)
310       */
311      public void removeAttribute(String name)
312      {
313        attrs.remove(name);
314      }
315    
316      /* (non-Javadoc)
317       * @see org.w3c.dom.Element#removeAttributeNode(org.w3c.dom.Attr)
318       */
319      public Attr removeAttributeNode(Attr oldAttr)
320      {
321        return (Attr)attrs.remove(oldAttr.getName());
322      }
323    
324      /* (non-Javadoc)
325       * @see org.w3c.dom.Element#removeAttributeNS(java.lang.String, java.lang.String)
326       */
327      public void removeAttributeNS(String namespaceURI, String localName)
328      {
329        removeAttribute(localName);
330      }
331    
332      /* (non-Javadoc)
333       * @see org.w3c.dom.Element#setAttribute(java.lang.String, java.lang.String)
334       */
335      public void setAttribute(String name, String value)
336      {
337        Attr attr = getAttributeNode(name);
338        if (attr != null)
339          attr.setValue(value);
340        else
341          attrs.put(name, new IIOMetadataNodeAttr(this, name, value));
342      }
343    
344      /* (non-Javadoc)
345       * @see org.w3c.dom.Element#setAttributeNode(org.w3c.dom.Attr)
346       */
347      public Attr setAttributeNode(Attr newAttr)
348      {
349        return (Attr)attrs.put(newAttr.getName(), newAttr);
350      }
351    
352      /* (non-Javadoc)
353       * @see org.w3c.dom.Element#setAttributeNodeNS(org.w3c.dom.Attr)
354       */
355      public Attr setAttributeNodeNS(Attr newAttr)
356      {
357        return (Attr)attrs.put(newAttr.getName(), newAttr);
358      }
359    
360      /* (non-Javadoc)
361       * @see org.w3c.dom.Element#setAttributeNS(java.lang.String, java.lang.String, java.lang.String)
362       */
363      public void setAttributeNS(String namespaceURI, String qualifiedName, String value)
364      {
365        setAttribute(qualifiedName, value);
366      }
367    
368      /* (non-Javadoc)
369       * @see org.w3c.dom.NodeList#getLength()
370       */
371      public int getLength()
372      {
373        return children.size();
374      }
375    
376      /* (non-Javadoc)
377       * @see org.w3c.dom.NodeList#item(int)
378       */
379      public Node item(int index)
380      {
381        if (index < children.size())
382          return (Node)children.get(index);
383        else
384          return null;
385      }
386    
387      /* (non-Javadoc)
388       * @see org.w3c.dom.Node#appendChild(org.w3c.dom.Node)
389       */
390      public Node appendChild(Node newChild)
391      {
392        if (newChild == null)
393          throw new IllegalArgumentException("Child node is null");
394    
395        IIOMetadataNode child = (IIOMetadataNode) newChild;
396    
397        children.add(child);
398        child.parent = this;
399        return this;
400      }
401    
402      /* (non-Javadoc)
403       * @see org.w3c.dom.Node#cloneNode(boolean)
404       */
405      public Node cloneNode(boolean deep)
406      {
407        IIOMetadataNode newnode = new IIOMetadataNode(name);
408        newnode.parent = null;
409        newnode.obj = obj;
410        if (deep)
411        {
412          for (int i=0; i < children.size(); i++)
413            newnode.children.add(((Node)children.get(i)).cloneNode(deep));
414        }
415    
416        // clone attrs
417        for (Iterator it = attrs.values().iterator(); it.hasNext();)
418        {
419          IIOMetadataNodeAttr attr = (IIOMetadataNodeAttr)it.next();
420          newnode.attrs.put(attr.name, attr.cloneNode(deep));
421          attr.owner = newnode;
422        }
423    
424        return newnode;
425      }
426    
427      /* (non-Javadoc)
428       * @see org.w3c.dom.Node#getAttributes()
429       */
430      public NamedNodeMap getAttributes()
431      {
432        return new IIONamedNodeMap(attrs);
433      }
434    
435      /* (non-Javadoc)
436       * @see org.w3c.dom.Node#getChildNodes()
437       */
438      public NodeList getChildNodes()
439      {
440        return this;
441      }
442    
443      public Object getFeature(String feature, String version)
444      {
445        return null;
446      }
447    
448      /* (non-Javadoc)
449       * @see org.w3c.dom.Node#getFirstChild()
450       */
451      public Node getFirstChild()
452      {
453        return (children.size() > 0) ? (Node)children.get(0) : null;
454      }
455    
456      /* (non-Javadoc)
457       * @see org.w3c.dom.Node#getLastChild()
458       */
459      public Node getLastChild()
460      {
461        return (children.size() > 0) ? (Node)children.get(children.size() - 1)
462               : null;
463      }
464    
465      /* (non-Javadoc)
466       * @see org.w3c.dom.Node#getLocalName()
467       */
468      public String getLocalName()
469      {
470        return name;
471      }
472    
473      /* (non-Javadoc)
474       * @see org.w3c.dom.Node#getNamespaceURI()
475       */
476      public String getNamespaceURI()
477      {
478        return null;
479      }
480    
481      /* (non-Javadoc)
482       * @see org.w3c.dom.Node#getNextSibling()
483       */
484      public Node getNextSibling()
485      {
486        // If this op needs to be faster, add links to prev and next nodes.
487        if (parent == null) return null;
488        int idx = parent.children.indexOf(this);
489        return (idx == parent.children.size() - 1) ? null
490            : (Node)parent.children.get(idx + 1);
491      }
492    
493      /* (non-Javadoc)
494       * @see org.w3c.dom.Node#getNodeName()
495       */
496      public String getNodeName()
497      {
498        return name;
499      }
500    
501      /* (non-Javadoc)
502       * @see org.w3c.dom.Node#getNodeType()
503       */
504      public short getNodeType()
505      {
506        return ELEMENT_NODE;
507      }
508    
509      /* (non-Javadoc)
510       * @see org.w3c.dom.Node#getNodeValue()
511       */
512      public String getNodeValue()
513      {
514        return null;
515      }
516    
517      /* (non-Javadoc)
518       * @see org.w3c.dom.Node#getOwnerDocument()
519       */
520      public Document getOwnerDocument()
521      {
522        // IOMetadataNodes have no owner
523        return null;
524      }
525    
526      /* (non-Javadoc)
527       * @see org.w3c.dom.Node#getParentNode()
528       */
529      public Node getParentNode()
530      {
531        return parent;
532      }
533    
534      /* (non-Javadoc)
535       * @see org.w3c.dom.Node#getPrefix()
536       */
537      public String getPrefix()
538      {
539        return null;
540      }
541    
542      /* (non-Javadoc)
543       * @see org.w3c.dom.Node#getPreviousSibling()
544       */
545      public Node getPreviousSibling()
546      {
547        // If this op needs to be faster, add links to prev and next nodes.
548        if (parent == null) return null;
549        int idx = parent.children.indexOf(this);
550        return (idx == 0) ? null
551            : (Node)parent.children.get(idx - 1);
552      }
553    
554      public TypeInfo getSchemaTypeInfo()
555      {
556        return null;
557      }
558    
559      public String getTextContent()
560        throws DOMException
561      {
562        return null;
563      }
564    
565      public Object getUserData(String key)
566      {
567        return null;
568      }
569    
570      /* (non-Javadoc)
571       * @see org.w3c.dom.Node#hasAttributes()
572       */
573      public boolean hasAttributes()
574      {
575        return !attrs.isEmpty();
576      }
577    
578      /* (non-Javadoc)
579       * @see org.w3c.dom.Node#hasChildNodes()
580       */
581      public boolean hasChildNodes()
582      {
583        return !children.isEmpty();
584      }
585    
586      /* (non-Javadoc)
587       * @see org.w3c.dom.Node#insertBefore(org.w3c.dom.Node, org.w3c.dom.Node)
588       */
589      public Node insertBefore(Node newChild, Node refChild)
590      {
591        if (newChild == null)
592          throw new IllegalArgumentException();
593    
594        int idx = children.indexOf(refChild);
595        if (idx == -1)
596          children.add(newChild);
597        else
598          children.add(idx, newChild);
599        ((IIOMetadataNode)newChild).parent = this;
600    
601        return newChild;
602      }
603    
604      public boolean isDefaultNamespace(String namespaceURI)
605      {
606        return true;
607      }
608    
609      public boolean isEqualNode(Node arg)
610      {
611        return true;
612      }
613    
614      public boolean isSameNode(Node other)
615      {
616        return this == other;
617      }
618    
619      /* (non-Javadoc)
620       * @see org.w3c.dom.Node#isSupported(java.lang.String, java.lang.String)
621       */
622      public boolean isSupported(String feature, String version)
623      {
624        // No DOM features are supported
625        return false;
626      }
627    
628      public String lookupNamespaceURI(String prefix)
629      {
630        return null;
631      }
632    
633      public String lookupPrefix(String namespaceURI)
634      {
635        return null;
636      }
637    
638      /* (non-Javadoc)
639       * @see org.w3c.dom.Node#normalize()
640       */
641      public void normalize()
642      {
643        // No text nodes so no action
644      }
645    
646      /* (non-Javadoc)
647       * @see org.w3c.dom.Node#removeChild(org.w3c.dom.Node)
648       */
649      public Node removeChild(Node oldChild)
650      {
651        if (oldChild == null)
652          throw new IllegalArgumentException();
653        children.remove(oldChild);
654        ((IIOMetadataNode)oldChild).parent = null;
655    
656        return oldChild;
657      }
658    
659      /* (non-Javadoc)
660       * @see org.w3c.dom.Node#replaceChild(org.w3c.dom.Node, org.w3c.dom.Node)
661       */
662      public Node replaceChild(Node newChild, Node oldChild)
663      {
664        if (newChild == null)
665          throw new IllegalArgumentException();
666        children.set(children.indexOf(oldChild), newChild);
667        ((IIOMetadataNode)oldChild).parent = null;
668        return oldChild;
669      }
670    
671      public void setIdAttribute(String name, boolean isId)
672        throws DOMException
673      {
674      }
675    
676      public void setIdAttributeNode(Attr idAttr, boolean isId)
677        throws DOMException
678      {
679      }
680    
681      public void setIdAttributeNS(String namespaceURI, String localName, boolean isId)
682        throws DOMException
683      {
684      }
685    
686      /* (non-Javadoc)
687       * @see org.w3c.dom.Node#setNodeValue(java.lang.String)
688       */
689      public void setNodeValue(String nodeValue) throws DOMException
690      {
691      }
692    
693      /* (non-Javadoc)
694       * @see org.w3c.dom.Node#setPrefix(java.lang.String)
695       */
696      public void setPrefix(String prefix)
697      {
698      }
699    
700      public void setTextContent(String textContent)
701        throws DOMException
702      {
703      }
704    
705      public Object setUserData(String key, Object data, UserDataHandler handler)
706      {
707        return null;
708      }
709    }