OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / javax / naming / ictxImpl / trans / GnuName.java
1 /* GnuName.java -- implementation of the javax.naming.Name
2    Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.javax.naming.ictxImpl.trans;
39
40 import java.util.Enumeration;
41 import java.util.NoSuchElementException;
42
43 import javax.naming.InvalidNameException;
44 import javax.naming.Name;
45
46 /**
47  * The implementation of the {@link Name}.
48  * 
49  * @author Audrius Meskauskas
50  */
51 public class GnuName
52     implements Name
53 {
54   /**
55    * The enumeration to traverse over name components.
56    */
57   class GnuNameEnum
58       implements Enumeration
59   {
60     /**
61      * Get the new enumeration that enumerates from the given position forward
62      * 
63      * @param position the position of the first name component to enumerate (0
64      *          means first element)
65      */
66     GnuNameEnum(int position)
67     {
68       nxt = from + position;
69     }
70
71     /**
72      * The position of the next enumeration component to be returned or -1 if
73      * the end has been reached.
74      */
75     int nxt;
76
77     /**
78      * Check if there are more elements in this enumeration.
79      */
80     public boolean hasMoreElements()
81     {
82       return nxt >= 0;
83     }
84
85     /**
86      * Return the next element or throw a NoSuchElementException if there is no
87      * any.
88      */
89     public Object nextElement()
90     {
91       if (nxt < 0)
92         throw new NoSuchElementException();
93       Object r = content[nxt++];
94
95       if (nxt - from == length)
96         nxt = - 1;
97
98       return r;
99     }
100   }
101
102   private static final long serialVersionUID = - 3617482732056931635L;
103
104   /**
105    * The hashcode
106    */
107   int hash;
108
109   /**
110    * The content buffer of the name. This buffer may be shared, so the array
111    * member content should never be modified.
112    */
113   String[] content;
114
115   /**
116    * The place, inclusive, where the name content starts in the content buffer.
117    */
118   int from;
119
120   /**
121    * The length of the name.
122    */
123   int length;
124
125   /**
126    * Creates the unitialised name.
127    */
128   protected GnuName()
129   {
130
131   }
132
133   /**
134    * Creates the name, containing from the given chain of the atomic components.
135    * 
136    * @param name the array, containing the name components.
137    */
138   public GnuName(String[] name)
139   {
140     this(name, 0, name.length);
141   }
142
143   /**
144    * Creates the name that uses the given portion of the array for its
145    * components.
146    */
147   public GnuName(String[] buffer, int useFrom, int useLength)
148   {
149     content = buffer;
150     from = useFrom;
151     length = useLength;
152   }
153
154   /**
155    * Inserts the given <code>String</code> component to this <code>Name</code>
156    * at the given index. The method modifies the current <code>Name</code> and
157    * then returns it.
158    * 
159    * @exception ArrayIndexOutOfBoundsException if the given index is smaller
160    *              then zero or greater then or equal to <code>size()</code>.
161    * @exception InvalidNameException if the given <code>String</code> is not a
162    *              valid component for this <code>Name</code>.
163    */
164   public Name add(int posn, String comp) throws InvalidNameException
165   {
166     String[] nc = new String[content.length + 1];
167     System.arraycopy(content, from, nc, 0, posn);
168     nc[posn] = comp;
169     System.arraycopy(content, from + posn, nc, posn + 1, length - posn);
170
171     content = nc;
172     from = 0;
173     length = content.length;
174     hash = 0;
175     return this;
176   }
177
178   /**
179    * Adds the given <code>String</code> component to the end of this
180    * <code>Name</code>. The method modifies the current <code>Name</code>
181    * and then returns it.
182    * 
183    * @exception InvalidNameException if the given <code>String</code> is not a
184    *              valid component for this <code>Name</code>.
185    */
186   public Name add(String comp) throws InvalidNameException
187   {
188     String[] nc = new String[content.length + 1];
189     System.arraycopy(content, from, nc, 0, length);
190     nc[nc.length - 1] = comp;
191
192     content = nc;
193     from = 0;
194     length = content.length;
195     hash = 0;
196     return this;
197   }
198
199   /**
200    * Inserts all the components of the given <code>Name</code> to this
201    * <code>Name</code> at the given index. Components after this index (if
202    * any) are shifted up. The method modifies the current <code>Name</code>
203    * and then returns it.
204    * 
205    * @exception ArrayIndexOutOfBoundsException if the given index is smaller
206    *              then zero or greater then or equal to <code>size()</code>.
207    * @exception InvalidNameException if any of the given components is not a
208    *              valid component for this <code>Name</code>.
209    */
210   public Name addAll(int posn, Name n) throws InvalidNameException
211   {
212     String[] nc = new String[length + n.size()];
213     System.arraycopy(content, from, nc, 0, posn);
214
215     int i = posn;
216     for (int p = 0; p < n.size(); i++, p++)
217       nc[i] = n.get(p);
218
219     System.arraycopy(content, from + posn, nc, i, length - posn);
220
221     length = length + n.size();
222     hash = 0;
223     content = nc;
224     return this;
225   }
226
227   /**
228    * Adds all the components of the given <code>Name</code> to the end of this
229    * <code>Name</code>. The method modifies the current <code>Name</code>
230    * and then returns it.
231    * 
232    * @exception InvalidNameException if any of the given components is not a
233    *              valid component for this <code>Name</code>.
234    */
235   public Name addAll(Name suffix) throws InvalidNameException
236   {
237     String[] nc = new String[length + suffix.size()];
238     System.arraycopy(content, from, nc, 0, length);
239
240     for (int i = length, p = 0; i < nc.length; i++, p++)
241       nc[i] = suffix.get(p);
242
243     length = length + suffix.size();
244     hash = 0;
245     content = nc;
246     return this;
247   }
248
249   /**
250    * Compares the given object to this <code>Name</code>. Returns a negative
251    * value if the given <code>Object</code> is smaller then this
252    * <code>Name</code>, a positive value if the <code>Object</code> is
253    * bigger, and zero if the are equal. If the <code>Object</code> is not of a
254    * class that can be compared to the class of this <code>Name</code> then a
255    * <code>ClassCastException</code> is thrown. Note that it is not guaranteed
256    * that <code>Name</code>s implemented in different classes can be
257    * compared. The definition of smaller, bigger and equal is up to the actual
258    * implementing class.
259    */
260   public int compareTo(Object obj)
261   {
262     Name n = (Name) obj;
263
264     int l = Math.min(length, n.size());
265     int c;
266
267     for (int i = 0; i < l; i++)
268       {
269         c = content[from + i].compareTo(n.get(i));
270         if (c != 0)
271           return c;
272       }
273     return length - n.size();
274   }
275
276   /**
277    * Returns <code>true</code> if this <code>Name</code> ends with the
278    * components of the given <code>Name</code>, <code>false</code>
279    * otherwise.
280    */
281   public boolean endsWith(Name n)
282   {
283     if (n.size() > length)
284       return false;
285
286     int ofs = length - n.size() + from;
287
288     for (int i = 0; i < n.size(); i++, ofs++)
289       if (! content[ofs].equals(n.get(i)))
290         return false;
291
292     return true;
293   }
294
295   /**
296    * Gets the component at the given index.
297    * 
298    * @exception ArrayIndexOutOfBoundsException if the given index is smaller
299    *              then zero or greater then or equal to <code>size()</code>.
300    */
301   public String get(int posn)
302   {
303     return content[from + posn];
304   }
305
306   /**
307    * Returns a non-null (but possibly empty) <code>Enumeration</code> of the
308    * components of the <code>Name</code> as <code>String</code>s.
309    */
310   public Enumeration getAll()
311   {
312     return new GnuNameEnum(0);
313   }
314
315   /**
316    * Returns the components till the given index as a <code>Name</code>. The
317    * returned <code>Name</code> can be modified without changing the original.
318    * 
319    * @param posn the ending position, exclusive
320    * @exception ArrayIndexOutOfBoundsException if the given index is smaller
321    *              then zero or greater then or equal to <code>size()</code>.
322    */
323   public Name getPrefix(int posn)
324   {
325     return new GnuName(content, from, posn);
326   }
327
328   /**
329    * Returns the components from the given index till the end as a
330    * <code>Name</code>. The returned <code>Name</code> can be modified
331    * without changing the original.
332    * 
333    * @param posn the starting position, inclusive. If it is equal to the size of
334    *          the name, the empty name is returned.
335    * @exception ArrayIndexOutOfBoundsException if the given index is smaller
336    *              then zero or greater then or equal to <code>size()</code>.
337    */
338   public Name getSuffix(int posn)
339   {
340     return new GnuName(content, from + posn, length - posn);
341   }
342
343   /**
344    * Returns <code>true</code> if the number of components of this
345    * <code>Name</code> is zero, <code>false</code> otherwise.
346    */
347   public boolean isEmpty()
348   {
349     return length == 0;
350   }
351
352   /**
353    * Removes the component at the given index from this <code>Name</code>.
354    * The method modifies the current <code>Name</code> and then returns it.
355    * 
356    * @exception InvalidNameException if the name size reduces below zero.
357    */
358   public Object remove(int posn) throws InvalidNameException
359   {
360     if (length == 0)
361       throw new InvalidNameException("negative size");
362     else
363       {
364         length--;
365         if (posn == 0)
366           from++;
367         else if (posn < length)
368           {
369             String[] nc = new String[length];
370             System.arraycopy(content, from, nc, 0, posn);
371             System.arraycopy(content, from + posn + 1, nc, posn, length - posn);
372             content = nc;
373             from = 0;
374           }
375       }
376     hash = 0;
377     return this;
378   }
379
380   /**
381    * Returns the number of components of this <code>Name</code>. The returned
382    * number can be zero.
383    */
384   public int size()
385   {
386     return length;
387   }
388
389   /**
390    * Returns <code>true</code> if this <code>Name</code> starts with the
391    * components of the given <code>Name</code>, <code>false</code>
392    * otherwise.
393    */
394   public boolean startsWith(Name n)
395   {
396     if (n.size() > length)
397       return false;
398
399     for (int i = 0; i < n.size(); i++)
400       if (! content[from + i].equals(n.get(i)))
401         return false;
402
403     return true;
404   }
405
406   /**
407    * Returns a clone of this <code>Name</code>. It will be a deep copy of all
408    * the components of the <code>Name</code> so that changes to components of
409    * the components does not change the component in this <code>Name</code>.
410    */
411   public Object clone()
412   {
413     return new GnuName(content, from, length);
414   }
415
416   /**
417    * The name is equal to other name if they contents are equal.
418    */
419   public boolean equals(Object arg0)
420   {
421     if (this == arg0)
422       return true;
423     else if (arg0 instanceof Name)
424       {
425         Name n = (Name) arg0;
426         if (length != n.size())
427           return false;
428
429         for (int i = 0; i < length; i++)
430           if (! content[from + i].equals(n.get(i)))
431             return false;
432         return true;
433       }
434     else
435       return false;
436   }
437
438   /**
439    * Overridden to make consistent with equals.
440    */
441   public int hashCode()
442   {
443     if (hash == 0 && length > 0)
444       {
445         int s = 0;
446         for (int i = from; i < from + length; i++)
447           s ^= content[i].hashCode();
448         hash = s;
449       }
450     return hash;
451   }
452
453   /**
454    * Get the string representation, separating the name components by slashes
455    */
456   public String toString()
457   {
458     StringBuffer b = new StringBuffer();
459     for (int i = 0; i < length; i++)
460       {
461         b.append(get(i));
462         if (i < length - 1)
463           b.append('/');
464       }
465     return b.toString();
466   }
467 }