001    /* BasicAttributes.java --
002       Copyright (C) 2000, 2001, 2004, 2005, 2006  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.naming.directory;
040    
041    import java.io.IOException;
042    import java.io.ObjectInputStream;
043    import java.io.ObjectOutputStream;
044    import java.util.NoSuchElementException;
045    import java.util.Vector;
046    
047    import javax.naming.NamingEnumeration;
048    import javax.naming.NamingException;
049    
050    /**
051     * @author Tom Tromey (tromey@redhat.com)
052     * @date June 22, 2001
053     */
054    public class BasicAttributes implements Attributes
055    {
056      private static final long serialVersionUID = 4980164073184639448L;
057    
058      public BasicAttributes ()
059      {
060        this (false);
061      }
062    
063      public BasicAttributes (boolean ignoreCase)
064      {
065        this.ignoreCase = ignoreCase;
066        this.attributes = new Vector<Attribute>();
067      }
068    
069      public BasicAttributes (String attrID, Object val)
070      {
071        this (attrID, val, false);
072      }
073    
074      public BasicAttributes (String attrID, Object val, boolean ignoreCase)
075      {
076        this.ignoreCase = ignoreCase;
077        attributes = new Vector<Attribute>();
078        attributes.add (new BasicAttribute (attrID, val));
079      }
080    
081      public Object clone ()
082      {
083        // Slightly inefficient as we make a garbage Vector here.
084        BasicAttributes ba = new BasicAttributes (ignoreCase);
085        ba.attributes = (Vector<Attribute>) attributes.clone ();
086        return ba;
087      }
088    
089      /**
090       * Returns true if and only if the given Object is an instance of
091       * Attributes, the given attributes both do or don't ignore case for
092       * IDs and the collection of attributes is the same.
093       */
094      public boolean equals (Object obj)
095      {
096        if (! (obj instanceof Attributes))
097          return false;
098    
099        Attributes bs = (Attributes) obj;
100        if (ignoreCase != bs.isCaseIgnored()
101            || attributes.size () != bs.size ())
102          return false;
103    
104        NamingEnumeration bas = bs.getAll();
105        while (bas.hasMoreElements())
106          {
107            Attribute a = (Attribute) bas.nextElement();
108            Attribute b = get(a.getID ());
109            if (! a.equals(b))
110              return false;
111          }
112    
113        return true;
114      }
115    
116      public Attribute get (String attrID)
117      {
118        for (int i = 0; i < attributes.size (); ++i)
119          {
120            Attribute at = attributes.get (i);
121            if ((ignoreCase && attrID.equalsIgnoreCase (at.getID ()))
122                || (! ignoreCase && attrID.equals (at.getID ())))
123              return at;
124          }
125    
126        return null;
127      }
128    
129      public NamingEnumeration<Attribute> getAll ()
130      {
131        return new BasicAttributesEnumeration();
132      }
133    
134      public NamingEnumeration<String> getIDs ()
135      {
136        final NamingEnumeration<Attribute> attrs = getAll();
137        return new NamingEnumeration<String>() {
138          public boolean hasMore() throws NamingException
139          {
140            return attrs.hasMore();
141          }
142    
143          public boolean hasMoreElements()
144          {
145            return attrs.hasMoreElements();
146          }
147    
148          public String next() throws NamingException
149          {
150            return attrs.next().getID();
151          }
152    
153          public String nextElement()
154          {
155            return attrs.nextElement().getID();
156          }
157    
158          public void close() throws NamingException
159          {
160            attrs.close();
161          }
162        };
163      }
164    
165      public int hashCode ()
166      {
167        int val = 0;
168        for (int i = 0; i < attributes.size (); ++i)
169          val += attributes.get (i).hashCode ();
170        return val;
171      }
172    
173      public boolean isCaseIgnored ()
174      {
175        return ignoreCase;
176      }
177    
178      public Attribute put (Attribute attr)
179      {
180        Attribute r = remove (attr.getID ());
181        attributes.add (attr);
182        return r;
183      }
184    
185      public Attribute put (String attrID, Object val)
186      {
187        return put (new BasicAttribute (attrID, val));
188      }
189    
190      public Attribute remove (String attrID)
191      {
192        for (int i = 0; i < attributes.size (); ++i)
193          {
194            Attribute at = (Attribute) attributes.get (i);
195            if ((ignoreCase && attrID.equalsIgnoreCase (at.getID ()))
196                || (! ignoreCase && attrID.equals (at.getID ())))
197              {
198                attributes.remove (i);
199                return at;
200              }
201          }
202    
203        return null;
204      }
205    
206      public int size ()
207      {
208        return attributes.size ();
209      }
210    
211      public String toString ()
212      {
213        String r = "";
214        for (int i = 0; i < attributes.size (); ++i)
215          {
216            if (i > 0)
217              r += "; ";
218            r += attributes.get (i).toString ();
219          }
220        return r;
221      }
222    
223      // This is set by the serialization spec.
224      private boolean ignoreCase;
225      // Package-private to avoid a trampoline.
226      transient Vector<Attribute> attributes;
227    
228      private void readObject(ObjectInputStream s) throws IOException,
229          ClassNotFoundException
230      {
231        s.defaultReadObject();
232        int size = s.readInt();
233        attributes = new Vector<Attribute>(size);
234        for (int i = 0; i < size; i++)
235          attributes.add((Attribute) s.readObject());
236      }
237    
238      private void writeObject(ObjectOutputStream s) throws IOException
239      {
240        s.defaultWriteObject();
241        s.writeInt(attributes.size());
242        for (int i = 0; i < attributes.size(); i++)
243          s.writeObject(attributes.get(i));
244      }
245    
246      // Used when enumerating.
247      private class BasicAttributesEnumeration
248        implements NamingEnumeration<Attribute>
249      {
250        int where = 0;
251    
252        public BasicAttributesEnumeration ()
253        {
254        }
255    
256        public void close () throws NamingException
257        {
258        }
259    
260        public boolean hasMore () throws NamingException
261        {
262          return hasMoreElements ();
263        }
264    
265        public Attribute next () throws NamingException
266        {
267          return nextElement ();
268        }
269    
270        public boolean hasMoreElements ()
271        {
272          return where < attributes.size ();
273        }
274    
275        public Attribute nextElement () throws NoSuchElementException
276        {
277          if (where >= attributes.size ())
278            throw new NoSuchElementException ("no more elements");
279          Attribute at = attributes.get (where);
280          ++where;
281          return at;
282        }
283      }
284    }