001    /* BasicAttribute.java --
002       Copyright (C) 2000, 2001, 2004, 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    import javax.naming.OperationNotSupportedException;
050    
051    /**
052     * @author Tom Tromey (tromey@redhat.com)
053     * @date June 20, 2001
054     * @since 1.3
055     */
056    public class BasicAttribute implements Attribute
057    {
058      private static final long serialVersionUID = 6743528196119291326L;
059    
060      /** The ID of this attribute.  */
061      protected String attrID;
062      /** True if this attribute's values are ordered.  */
063      protected boolean ordered;
064      /** Values for this attribute.  */
065      protected transient Vector<Object> values;
066    
067      // Used by cloning.
068      private BasicAttribute ()
069      {
070      }
071    
072      public BasicAttribute (String id)
073      {
074        this (id, false);
075      }
076    
077      public BasicAttribute (String id, boolean ordered)
078      {
079        attrID = id;
080        this.ordered = ordered;
081        values = new Vector<Object> ();
082      }
083    
084      public BasicAttribute (String id, Object value)
085      {
086        this (id, value, false);
087      }
088    
089      public BasicAttribute (String id, Object value, boolean ordered)
090      {
091        attrID = id;
092        this.ordered = ordered;
093        values = new Vector<Object> ();
094        values.add (value);
095      }
096    
097      public void add (int index, Object val)
098      {
099        if (! ordered && contains (val))
100          throw new IllegalStateException ("value already in attribute");
101        values.add (index, val);
102      }
103    
104      public boolean add (Object val)
105      {
106        if (! ordered && contains (val))
107          throw new IllegalStateException ("value already in attribute");
108        return values.add (val);
109      }
110    
111      public void clear ()
112      {
113        values.clear ();
114      }
115    
116      public Object clone ()
117      {
118        BasicAttribute c = new BasicAttribute ();
119        c.attrID = attrID;
120        c.ordered = ordered;
121        c.values = (Vector<Object>) values.clone ();
122        return c;
123      }
124    
125      public boolean contains (Object val)
126      {
127        for (int i = 0; i < values.size (); ++i)
128          {
129            if (equals (val, values.get (i)))
130              return true;
131          }
132    
133        return false;
134      }
135    
136      public boolean equals (Object obj)
137      {
138        if (! (obj instanceof BasicAttribute))
139          return false;
140        BasicAttribute b = (BasicAttribute) obj;
141    
142        if (ordered != b.ordered
143            || ! attrID.equals (b.attrID)
144            || values.size () != b.values.size ())
145          return false;
146    
147        for (int i = 0; i < values.size (); ++i)
148          {
149            boolean ok = false;
150            if (ordered)
151              ok = equals (values.get (i), b.values.get (i));
152            else
153              {
154                for (int j = 0; j < b.values.size (); ++j)
155                  {
156                    if (equals (values.get (i), b.values.get (j)))
157                      {
158                        ok = true;
159                        break;
160                      }
161                  }
162              }
163    
164            if (! ok)
165              return false;
166          }
167    
168        return true;
169      }
170    
171      public Object get ()
172        throws NamingException
173      {
174        if (values.size () == 0)
175          throw new NoSuchElementException ("no values");
176        return get (0);
177      }
178    
179      public Object get (int index)
180        throws NamingException
181      {
182        return values.get (index);
183      }
184    
185      public NamingEnumeration<?> getAll ()
186        throws NamingException
187      {
188        return new BasicAttributeEnumeration ();
189      }
190    
191      public DirContext getAttributeDefinition ()
192        throws OperationNotSupportedException, NamingException
193      {
194        throw new OperationNotSupportedException ();
195      }
196    
197      public DirContext getAttributeSyntaxDefinition ()
198        throws OperationNotSupportedException, NamingException
199      {
200        throw new OperationNotSupportedException ();
201      }
202    
203      public String getID ()
204      {
205        return attrID;
206      }
207    
208      public int hashCode ()
209      {
210        int val = attrID.hashCode ();
211        for (int i = 0; i < values.size (); ++i)
212          {
213            Object o = values.get (i);
214            if (o == null)
215              {
216                // Nothing.
217              }
218            else if (o instanceof Object[])
219              {
220                Object[] a = (Object[]) o;
221                for (int j = 0; j < a.length; ++j)
222                  val += a[j].hashCode ();
223              }
224            else
225              val += o.hashCode ();
226          }
227    
228        return val;
229      }
230    
231      public boolean isOrdered ()
232      {
233        return ordered;
234      }
235    
236      public Object remove (int index)
237      {
238        return values.remove (index);
239      }
240    
241      public boolean remove (Object val)
242      {
243        for (int i = 0; i < values.size (); ++i)
244          {
245            if (equals (val, values.get (i)))
246              {
247                values.remove (i);
248                return true;
249              }
250          }
251    
252        return false;
253      }
254    
255      public Object set (int index, Object val)
256      {
257        if (! ordered && contains (val))
258          throw new IllegalStateException ("value already in attribute");
259        return values.set (index, val);
260      }
261    
262      public int size ()
263      {
264        return values.size ();
265      }
266    
267      public String toString ()
268      {
269        String r = attrID;
270        for (int i = 0; i < values.size (); ++i)
271          r += ";" + values.get (i).toString ();
272        return r;
273      }
274    
275      // This is used for testing equality of two Objects according to our
276      // local rules.
277      private boolean equals (Object one, Object two)
278      {
279        if (one == null)
280          return two == null;
281    
282        if (one instanceof Object[])
283          {
284            if (! (two instanceof Object[]))
285              return false;
286    
287            Object[] aone = (Object[]) one;
288            Object[] atwo = (Object[]) two;
289    
290            if (aone.length != atwo.length)
291              return false;
292    
293            for (int i = 0; i < aone.length; ++i)
294              {
295                if (! aone[i].equals (atwo[i]))
296                  return false;
297              }
298    
299            return true;
300          }
301    
302        return one.equals (two);
303      }
304    
305      private void readObject(ObjectInputStream s)
306        throws IOException, ClassNotFoundException
307      {
308        s.defaultReadObject();
309        int size = s.readInt();
310        values = new Vector<Object>(size);
311        for (int i=0; i < size; i++)
312          values.add(s.readObject());
313      }
314    
315      private void writeObject(ObjectOutputStream s) throws IOException
316      {
317        s.defaultWriteObject();
318        s.writeInt(values.size());
319        for (int i=0; i < values.size(); i++)
320          s.writeObject(values.get(i));
321      }
322    
323      // Used when enumerating this attribute.
324      private class BasicAttributeEnumeration implements NamingEnumeration
325      {
326        int where = 0;
327    
328        public BasicAttributeEnumeration ()
329        {
330        }
331    
332        public void close () throws NamingException
333        {
334        }
335    
336        public boolean hasMore () throws NamingException
337        {
338          return hasMoreElements ();
339        }
340    
341        public Object next () throws NamingException
342        {
343          return nextElement ();
344        }
345    
346        public boolean hasMoreElements ()
347        {
348          return where < values.size ();
349        }
350    
351        public Object nextElement () throws NoSuchElementException
352        {
353          if (where == values.size ())
354            throw new NoSuchElementException ("no more elements");
355          return values.get (where++);
356        }
357      }
358    }