001/* IIOMetadataNode.java --
002   Copyright (C) 2004  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.imageio.metadata;
040
041import java.util.ArrayList;
042import java.util.HashMap;
043import java.util.Iterator;
044import java.util.List;
045
046import org.w3c.dom.Attr;
047import org.w3c.dom.DOMException;
048import org.w3c.dom.Document;
049import org.w3c.dom.Element;
050import org.w3c.dom.NamedNodeMap;
051import org.w3c.dom.Node;
052import org.w3c.dom.NodeList;
053import org.w3c.dom.TypeInfo;
054import org.w3c.dom.UserDataHandler;
055import javax.imageio.metadata.IIOMetadataFormatImpl.IIOMetadataNodeAttr;
056
057public 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}