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 }