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