001package com.hfg.xml;
002
003import java.util.*;
004
005import org.w3c.dom.NamedNodeMap;
006import org.w3c.dom.Node;
007import org.w3c.dom.DOMException;
008
009import com.hfg.util.collection.CollectionUtil;
010
011
012public class XMLAttributeMap implements NamedNodeMap, Set<XMLAttribute>
013{
014
015   //###########################################################################
016   // PRIVATE FIELDS
017   //###########################################################################
018
019   // Stored internally as a SortedMap so that attributes will be output consistently
020   // (alphabetically).
021   private TreeMap<String, XMLAttribute> mMap = new TreeMap<String, XMLAttribute>();
022
023
024   //###########################################################################
025   // PUBLIC METHODS
026   //###########################################################################
027
028
029   // Methods for interface NamedNodeMap
030
031   //---------------------------------------------------------------------------
032   public Node getNamedItem(String inName)
033   {
034      return mMap.get(inName);
035   }
036
037   //---------------------------------------------------------------------------
038   public Node setNamedItem(Node inNode) throws DOMException
039   {
040      Node result = null;
041      if (inNode != null)
042      {
043         if (inNode.getNodeType() != Node.ATTRIBUTE_NODE)
044         {
045            throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
046                                   "The added node must be an attribute!");
047         }
048
049         XMLAttribute attr = null;
050         if (inNode instanceof XMLAttribute)
051         {
052            attr = (XMLAttribute) inNode;
053         }
054         else
055         {
056            attr = new XMLAttribute(inNode.getNodeName(), inNode.getNodeValue());
057            // TODO: attitional things like namespace that need to be passed?
058         }
059
060         result = mMap.put(attr.getName(), attr);
061      }
062
063      return result;
064   }
065
066   //---------------------------------------------------------------------------
067   public Node removeNamedItem(String inName) throws DOMException
068   {
069      return mMap.remove(inName);
070   }
071
072   //---------------------------------------------------------------------------
073   public Node item(int i)
074   {
075      Node node = null;
076      int index = 0;
077      for (XMLAttribute attr : mMap.values())
078      {
079         if (index == i)
080         {
081            node = attr;
082            break;
083         }
084         index++;
085      }
086
087      return node;
088   }
089
090   //---------------------------------------------------------------------------
091   public int getLength()
092   {
093      return mMap.size();
094   }
095
096   //---------------------------------------------------------------------------
097   public Node getNamedItemNS(String inNamespaceURI, String inLocalName) throws DOMException
098   {
099      return null;  //To change body of implemented methods use File | Settings | File Templates.
100   }
101
102   //---------------------------------------------------------------------------
103   public Node setNamedItemNS(Node node) throws DOMException
104   {
105      return null;  //To change body of implemented methods use File | Settings | File Templates.
106   }
107
108   //---------------------------------------------------------------------------
109   public Node removeNamedItemNS(String inNamespaceURI, String inLocalName) throws DOMException
110   {
111      return null;  //To change body of implemented methods use File | Settings | File Templates.
112   }
113
114
115   // Methods for interface Set
116
117   //---------------------------------------------------------------------------
118   public int size()
119   {
120      return mMap.size();
121   }
122
123   //---------------------------------------------------------------------------
124   public boolean isEmpty()
125   {
126      return mMap.isEmpty();
127   }
128
129   //---------------------------------------------------------------------------
130   public boolean contains(Object inObject)
131   {
132      return mMap.containsValue(inObject);
133   }
134
135   //---------------------------------------------------------------------------
136   public Iterator<XMLAttribute> iterator()
137   {
138      return mMap.values().iterator();
139   }
140
141   //---------------------------------------------------------------------------
142   public Object[] toArray()
143   {
144      return mMap.values().toArray();
145   }
146
147   //---------------------------------------------------------------------------
148   public <T>T[] toArray(T[] ts)
149   {
150      return mMap.values().toArray(ts);
151   }
152
153   //---------------------------------------------------------------------------
154   public boolean add(XMLAttribute inXMLAttribute)
155   {
156      boolean result = false;
157      if (inXMLAttribute != null)
158      {
159         result = mMap.containsKey(inXMLAttribute.getName());
160         mMap.put(inXMLAttribute.getName(), inXMLAttribute);
161      }
162
163      return result;
164   }
165
166   //---------------------------------------------------------------------------
167   public boolean remove(Object inObject)
168   {
169      boolean result = false;
170      if (mMap.containsValue(inObject))
171      {
172         XMLAttribute attr = (XMLAttribute) inObject;
173         mMap.remove(attr.getName());
174         result = true;
175      }
176
177      return result;
178   }
179
180   //---------------------------------------------------------------------------
181   public boolean containsAll(Collection<?> inObjects)
182   {
183      boolean result = true;
184      if (CollectionUtil.hasValues(inObjects))
185      {
186         for (Object obj : inObjects)
187         {
188            // TODO: Note that this is comparing Object signatures. Should we compare attribute names?
189            if (!mMap.containsValue(obj))
190            {
191               result = false;
192            }
193         }
194      }
195
196      return result;
197   }
198
199   //---------------------------------------------------------------------------
200   public boolean addAll(Collection<? extends XMLAttribute> inXMLAttributes)
201   {
202      boolean changed = false;
203      if (CollectionUtil.hasValues(inXMLAttributes))
204      {
205         for (XMLAttribute attr : inXMLAttributes)
206         {
207            if (!mMap.containsKey(attr.getName()))
208            {
209               changed = true;
210            }
211
212            mMap.put(attr.getName(), attr);
213         }
214      }
215
216      return changed;
217   }
218
219   //---------------------------------------------------------------------------
220   public boolean retainAll(Collection<?> inObjects)
221   {
222      boolean changed = false;
223      if (CollectionUtil.hasValues(inObjects))
224      {
225         for (XMLAttribute attr : mMap.values())
226         {
227            if (!inObjects.contains(attr))
228            {
229               mMap.remove(attr.getName());
230               changed = true;
231            }
232         }
233      }
234
235      return changed;
236   }
237
238   //---------------------------------------------------------------------------
239   public boolean removeAll(Collection<?> inObjects)
240   {
241      boolean changed = false;
242      if (CollectionUtil.hasValues(inObjects))
243      {
244         for (Object obj : inObjects)
245         {
246            if (mMap.containsValue(obj))
247            {
248               mMap.remove(((XMLAttribute)obj).getName());
249               changed = true;
250            }
251         }
252      }
253
254      return changed;
255   }
256
257   //---------------------------------------------------------------------------
258   public void clear()
259   {
260      mMap.clear();
261   }
262}