Source for gnu.javax.naming.ictxImpl.trans.GnuName

   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: }