001/* BasicAttributes.java --
002   Copyright (C) 2000, 2001, 2004, 2005, 2006  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.naming.directory;
040
041import java.io.IOException;
042import java.io.ObjectInputStream;
043import java.io.ObjectOutputStream;
044import java.util.NoSuchElementException;
045import java.util.Vector;
046
047import javax.naming.NamingEnumeration;
048import javax.naming.NamingException;
049
050/**
051 * @author Tom Tromey (tromey@redhat.com)
052 * @date June 22, 2001
053 */
054public 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}