< prev index next >

src/java.naming/share/classes/javax/naming/directory/BasicAttribute.java

Print this page




  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.naming.directory;
  27 
  28 import java.util.Vector;
  29 import java.util.Enumeration;
  30 import java.util.NoSuchElementException;
  31 import java.lang.reflect.Array;
  32 
  33 import javax.naming.NamingException;
  34 import javax.naming.NamingEnumeration;
  35 import javax.naming.OperationNotSupportedException;
  36 
  37 /**
  38   * This class provides a basic implementation of the <tt>Attribute</tt> interface.
  39   *<p>
  40   * This implementation does not support the schema methods
  41   * <tt>getAttributeDefinition()</tt> and <tt>getAttributeSyntaxDefinition()</tt>.
  42   * They simply throw <tt>OperationNotSupportedException</tt>.
  43   * Subclasses of <tt>BasicAttribute</tt> should override these methods if they
  44   * support them.
  45   *<p>
  46   * The <tt>BasicAttribute</tt> class by default uses <tt>Object.equals()</tt> to
  47   * determine equality of attribute values when testing for equality or
  48   * when searching for values, <em>except</em> when the value is an array.
  49   * For an array, each element of the array is checked using <tt>Object.equals()</tt>.
  50   * Subclasses of <tt>BasicAttribute</tt> can make use of schema information
  51   * when doing similar equality checks by overriding methods
  52   * in which such use of schema is meaningful.
  53   * Similarly, the <tt>BasicAttribute</tt> class by default returns the values passed to its
  54   * constructor and/or manipulated using the add/remove methods.
  55   * Subclasses of <tt>BasicAttribute</tt> can override <tt>get()</tt> and <tt>getAll()</tt>
  56   * to get the values dynamically from the directory (or implement
  57   * the <tt>Attribute</tt> interface directly instead of subclassing <tt>BasicAttribute</tt>).
  58   *<p>
  59   * Note that updates to <tt>BasicAttribute</tt> (such as adding or removing a value)
  60   * does not affect the corresponding representation of the attribute
  61   * in the directory.  Updates to the directory can only be effected
  62   * using operations in the <tt>DirContext</tt> interface.
  63   *<p>
  64   * A <tt>BasicAttribute</tt> instance is not synchronized against concurrent
  65   * multithreaded access. Multiple threads trying to access and modify a
  66   * <tt>BasicAttribute</tt> should lock the object.
  67   *
  68   * @author Rosanna Lee
  69   * @author Scott Seligman
  70   * @since 1.3
  71   */
  72 public class BasicAttribute implements Attribute {
  73     /**
  74      * Holds the attribute's id. It is initialized by the public constructor and
  75      * cannot be null unless methods in BasicAttribute that use attrID
  76      * have been overridden.
  77      * @serial
  78      */
  79     protected String attrID;
  80 
  81     /**
  82      * Holds the attribute's values. Initialized by public constructors.
  83      * Cannot be null unless methods in BasicAttribute that use
  84      * values have been overridden.
  85      */
  86     protected transient Vector<Object> values;


  95     public Object clone() {
  96         BasicAttribute attr;
  97         try {
  98             attr = (BasicAttribute)super.clone();
  99         } catch (CloneNotSupportedException e) {
 100             attr = new BasicAttribute(attrID, ordered);
 101         }
 102         attr.values = (Vector<Object>)values.clone();
 103         return attr;
 104     }
 105 
 106     /**
 107       * Determines whether obj is equal to this attribute.
 108       * Two attributes are equal if their attribute-ids, syntaxes
 109       * and values are equal.
 110       * If the attribute values are unordered, the order that the values were added
 111       * are irrelevant. If the attribute values are ordered, then the
 112       * order the values must match.
 113       * If obj is null or not an Attribute, false is returned.
 114       *<p>
 115       * By default <tt>Object.equals()</tt> is used when comparing the attribute
 116       * id and its values except when a value is an array. For an array,
 117       * each element of the array is checked using <tt>Object.equals()</tt>.
 118       * A subclass may override this to make
 119       * use of schema syntax information and matching rules,
 120       * which define what it means for two attributes to be equal.
 121       * How and whether a subclass makes
 122       * use of the schema information is determined by the subclass.
 123       * If a subclass overrides <tt>equals()</tt>, it should also override
 124       * <tt>hashCode()</tt>
 125       * such that two attributes that are equal have the same hash code.
 126       *
 127       * @param obj      The possibly null object to check.
 128       * @return true if obj is equal to this attribute; false otherwise.
 129       * @see #hashCode
 130       * @see #contains
 131       */
 132     public boolean equals(Object obj) {
 133         if ((obj != null) && (obj instanceof Attribute)) {
 134             Attribute target = (Attribute)obj;
 135 
 136             // Check order first
 137             if (isOrdered() != target.isOrdered()) {
 138                 return false;
 139             }
 140             int len;
 141             if (attrID.equals(target.getID()) &&
 142                 (len=size()) == target.size()) {
 143                 try {
 144                     if (isOrdered()) {


 155                             if (find(theirs.nextElement()) < 0)
 156                                 return false;
 157                         }
 158                     }
 159                 } catch (NamingException e) {
 160                     return false;
 161                 }
 162                 return true;
 163             }
 164         }
 165         return false;
 166     }
 167 
 168     /**
 169       * Calculates the hash code of this attribute.
 170       *<p>
 171       * The hash code is computed by adding the hash code of
 172       * the attribute's id and that of all of its values except for
 173       * values that are arrays.
 174       * For an array, the hash code of each element of the array is summed.
 175       * If a subclass overrides <tt>hashCode()</tt>, it should override
 176       * <tt>equals()</tt>
 177       * as well so that two attributes that are equal have the same hash code.
 178       *
 179       * @return an int representing the hash code of this attribute.
 180       * @see #equals
 181       */
 182     public int hashCode() {
 183         int hash = attrID.hashCode();
 184         int num = values.size();
 185         Object val;
 186         for (int i = 0; i < num; i ++) {
 187             val = values.elementAt(i);
 188             if (val != null) {
 189                 if (val.getClass().isArray()) {
 190                     Object it;
 191                     int len = Array.getLength(val);
 192                     for (int j = 0 ; j < len ; j++) {
 193                         it = Array.get(val, j);
 194                         if (it != null) {
 195                             hash += it.hashCode();
 196                         }


 298         if (values.size() == 0) {
 299             throw new
 300         NoSuchElementException("Attribute " + getID() + " has no value");
 301         } else {
 302             return values.elementAt(0);
 303         }
 304     }
 305 
 306     public int size() {
 307       return values.size();
 308     }
 309 
 310     public String getID() {
 311         return attrID;
 312     }
 313 
 314     /**
 315       * Determines whether a value is in this attribute.
 316       *<p>
 317       * By default,
 318       * <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
 319       * with this attribute's values except when <tt>attrVal</tt> is an array.
 320       * For an array, each element of the array is checked using
 321       * <tt>Object.equals()</tt>.
 322       * A subclass may use schema information to determine equality.
 323       */
 324     public boolean contains(Object attrVal) {
 325         return (find(attrVal) >= 0);
 326     }
 327 
 328     // For finding first element that has a null in JDK1.1 Vector.
 329     // In the Java 2 platform, can just replace this with Vector.indexOf(target);
 330     private int find(Object target) {
 331         Class<?> cl;
 332         if (target == null) {
 333             int ct = values.size();
 334             for (int i = 0 ; i < ct ; i++) {
 335                 if (values.elementAt(i) == null)
 336                     return i;
 337             }
 338         } else if ((cl=target.getClass()).isArray()) {
 339             int ct = values.size();
 340             Object it;
 341             for (int i = 0 ; i < ct ; i++) {
 342                 it = values.elementAt(i);
 343                 if (it != null && cl == it.getClass()
 344                     && arrayEquals(target, it))
 345                     return i;
 346             }
 347         } else {
 348             return values.indexOf(target, 0);
 349         }
 350         return -1;  // not found
 351     }
 352 
 353     /**
 354      * Determines whether two attribute values are equal.
 355      * Use arrayEquals for arrays and <tt>Object.equals()</tt> otherwise.
 356      */
 357     private static boolean valueEquals(Object obj1, Object obj2) {
 358         if (obj1 == obj2) {
 359             return true; // object references are equal
 360         }
 361         if (obj1 == null) {
 362             return false; // obj2 was not false
 363         }
 364         if (obj1.getClass().isArray() &&
 365             obj2.getClass().isArray()) {
 366             return arrayEquals(obj1, obj2);
 367         }
 368         return (obj1.equals(obj2));
 369     }
 370 
 371     /**
 372      * Determines whether two arrays are equal by comparing each of their
 373      * elements using <tt>Object.equals()</tt>.
 374      */
 375     private static boolean arrayEquals(Object a1, Object a2) {
 376         int len;
 377         if ((len = Array.getLength(a1)) != Array.getLength(a2))
 378             return false;
 379 
 380         for (int j = 0; j < len; j++) {
 381             Object i1 = Array.get(a1, j);
 382             Object i2 = Array.get(a2, j);
 383             if (i1 == null || i2 == null) {
 384                 if (i1 != i2)
 385                     return false;
 386             } else if (!i1.equals(i2)) {
 387                 return false;
 388             }
 389         }
 390         return true;
 391     }
 392 
 393     /**
 394       * Adds a new value to this attribute.
 395       *<p>
 396       * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
 397       * with this attribute's values except when <tt>attrVal</tt> is an array.
 398       * For an array, each element of the array is checked using
 399       * <tt>Object.equals()</tt>.
 400       * A subclass may use schema information to determine equality.
 401       */
 402     public boolean add(Object attrVal) {
 403         if (isOrdered() || (find(attrVal) < 0)) {
 404             values.addElement(attrVal);
 405             return true;
 406         } else {
 407             return false;
 408         }
 409     }
 410 
 411     /**
 412       * Removes a specified value from this attribute.
 413       *<p>
 414       * By default, <tt>Object.equals()</tt> is used when comparing <tt>attrVal</tt>
 415       * with this attribute's values except when <tt>attrVal</tt> is an array.
 416       * For an array, each element of the array is checked using
 417       * <tt>Object.equals()</tt>.
 418       * A subclass may use schema information to determine equality.
 419       */
 420     public boolean remove(Object attrval) {
 421         // For the Java 2 platform, can just use "return removeElement(attrval);"
 422         // Need to do the following to handle null case
 423 
 424         int i = find(attrval);
 425         if (i >= 0) {
 426             values.removeElementAt(i);
 427             return true;
 428         }
 429         return false;
 430     }
 431 
 432     public void clear() {
 433         values.setSize(0);
 434     }
 435 
 436 //  ---- ordering methods
 437 




  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.naming.directory;
  27 
  28 import java.util.Vector;
  29 import java.util.Enumeration;
  30 import java.util.NoSuchElementException;
  31 import java.lang.reflect.Array;
  32 
  33 import javax.naming.NamingException;
  34 import javax.naming.NamingEnumeration;
  35 import javax.naming.OperationNotSupportedException;
  36 
  37 /**
  38   * This class provides a basic implementation of the {@code Attribute} interface.
  39   *<p>
  40   * This implementation does not support the schema methods
  41   * {@code getAttributeDefinition()} and {@code getAttributeSyntaxDefinition()}.
  42   * They simply throw {@code OperationNotSupportedException}.
  43   * Subclasses of {@code BasicAttribute} should override these methods if they
  44   * support them.
  45   *<p>
  46   * The {@code BasicAttribute} class by default uses {@code Object.equals()} to
  47   * determine equality of attribute values when testing for equality or
  48   * when searching for values, <em>except</em> when the value is an array.
  49   * For an array, each element of the array is checked using {@code Object.equals()}.
  50   * Subclasses of {@code BasicAttribute} can make use of schema information
  51   * when doing similar equality checks by overriding methods
  52   * in which such use of schema is meaningful.
  53   * Similarly, the {@code BasicAttribute} class by default returns the values passed to its
  54   * constructor and/or manipulated using the add/remove methods.
  55   * Subclasses of {@code BasicAttribute} can override {@code get()} and {@code getAll()}
  56   * to get the values dynamically from the directory (or implement
  57   * the {@code Attribute} interface directly instead of subclassing {@code BasicAttribute}).
  58   *<p>
  59   * Note that updates to {@code BasicAttribute} (such as adding or removing a value)
  60   * does not affect the corresponding representation of the attribute
  61   * in the directory.  Updates to the directory can only be effected
  62   * using operations in the {@code DirContext} interface.
  63   *<p>
  64   * A {@code BasicAttribute} instance is not synchronized against concurrent
  65   * multithreaded access. Multiple threads trying to access and modify a
  66   * {@code BasicAttribute} should lock the object.
  67   *
  68   * @author Rosanna Lee
  69   * @author Scott Seligman
  70   * @since 1.3
  71   */
  72 public class BasicAttribute implements Attribute {
  73     /**
  74      * Holds the attribute's id. It is initialized by the public constructor and
  75      * cannot be null unless methods in BasicAttribute that use attrID
  76      * have been overridden.
  77      * @serial
  78      */
  79     protected String attrID;
  80 
  81     /**
  82      * Holds the attribute's values. Initialized by public constructors.
  83      * Cannot be null unless methods in BasicAttribute that use
  84      * values have been overridden.
  85      */
  86     protected transient Vector<Object> values;


  95     public Object clone() {
  96         BasicAttribute attr;
  97         try {
  98             attr = (BasicAttribute)super.clone();
  99         } catch (CloneNotSupportedException e) {
 100             attr = new BasicAttribute(attrID, ordered);
 101         }
 102         attr.values = (Vector<Object>)values.clone();
 103         return attr;
 104     }
 105 
 106     /**
 107       * Determines whether obj is equal to this attribute.
 108       * Two attributes are equal if their attribute-ids, syntaxes
 109       * and values are equal.
 110       * If the attribute values are unordered, the order that the values were added
 111       * are irrelevant. If the attribute values are ordered, then the
 112       * order the values must match.
 113       * If obj is null or not an Attribute, false is returned.
 114       *<p>
 115       * By default {@code Object.equals()} is used when comparing the attribute
 116       * id and its values except when a value is an array. For an array,
 117       * each element of the array is checked using {@code Object.equals()}.
 118       * A subclass may override this to make
 119       * use of schema syntax information and matching rules,
 120       * which define what it means for two attributes to be equal.
 121       * How and whether a subclass makes
 122       * use of the schema information is determined by the subclass.
 123       * If a subclass overrides {@code equals()}, it should also override
 124       * {@code hashCode()}
 125       * such that two attributes that are equal have the same hash code.
 126       *
 127       * @param obj      The possibly null object to check.
 128       * @return true if obj is equal to this attribute; false otherwise.
 129       * @see #hashCode
 130       * @see #contains
 131       */
 132     public boolean equals(Object obj) {
 133         if ((obj != null) && (obj instanceof Attribute)) {
 134             Attribute target = (Attribute)obj;
 135 
 136             // Check order first
 137             if (isOrdered() != target.isOrdered()) {
 138                 return false;
 139             }
 140             int len;
 141             if (attrID.equals(target.getID()) &&
 142                 (len=size()) == target.size()) {
 143                 try {
 144                     if (isOrdered()) {


 155                             if (find(theirs.nextElement()) < 0)
 156                                 return false;
 157                         }
 158                     }
 159                 } catch (NamingException e) {
 160                     return false;
 161                 }
 162                 return true;
 163             }
 164         }
 165         return false;
 166     }
 167 
 168     /**
 169       * Calculates the hash code of this attribute.
 170       *<p>
 171       * The hash code is computed by adding the hash code of
 172       * the attribute's id and that of all of its values except for
 173       * values that are arrays.
 174       * For an array, the hash code of each element of the array is summed.
 175       * If a subclass overrides {@code hashCode()}, it should override
 176       * {@code equals()}
 177       * as well so that two attributes that are equal have the same hash code.
 178       *
 179       * @return an int representing the hash code of this attribute.
 180       * @see #equals
 181       */
 182     public int hashCode() {
 183         int hash = attrID.hashCode();
 184         int num = values.size();
 185         Object val;
 186         for (int i = 0; i < num; i ++) {
 187             val = values.elementAt(i);
 188             if (val != null) {
 189                 if (val.getClass().isArray()) {
 190                     Object it;
 191                     int len = Array.getLength(val);
 192                     for (int j = 0 ; j < len ; j++) {
 193                         it = Array.get(val, j);
 194                         if (it != null) {
 195                             hash += it.hashCode();
 196                         }


 298         if (values.size() == 0) {
 299             throw new
 300         NoSuchElementException("Attribute " + getID() + " has no value");
 301         } else {
 302             return values.elementAt(0);
 303         }
 304     }
 305 
 306     public int size() {
 307       return values.size();
 308     }
 309 
 310     public String getID() {
 311         return attrID;
 312     }
 313 
 314     /**
 315       * Determines whether a value is in this attribute.
 316       *<p>
 317       * By default,
 318       * {@code Object.equals()} is used when comparing {@code attrVal}
 319       * with this attribute's values except when {@code attrVal} is an array.
 320       * For an array, each element of the array is checked using
 321       * {@code Object.equals()}.
 322       * A subclass may use schema information to determine equality.
 323       */
 324     public boolean contains(Object attrVal) {
 325         return (find(attrVal) >= 0);
 326     }
 327 
 328     // For finding first element that has a null in JDK1.1 Vector.
 329     // In the Java 2 platform, can just replace this with Vector.indexOf(target);
 330     private int find(Object target) {
 331         Class<?> cl;
 332         if (target == null) {
 333             int ct = values.size();
 334             for (int i = 0 ; i < ct ; i++) {
 335                 if (values.elementAt(i) == null)
 336                     return i;
 337             }
 338         } else if ((cl=target.getClass()).isArray()) {
 339             int ct = values.size();
 340             Object it;
 341             for (int i = 0 ; i < ct ; i++) {
 342                 it = values.elementAt(i);
 343                 if (it != null && cl == it.getClass()
 344                     && arrayEquals(target, it))
 345                     return i;
 346             }
 347         } else {
 348             return values.indexOf(target, 0);
 349         }
 350         return -1;  // not found
 351     }
 352 
 353     /**
 354      * Determines whether two attribute values are equal.
 355      * Use arrayEquals for arrays and {@code Object.equals()} otherwise.
 356      */
 357     private static boolean valueEquals(Object obj1, Object obj2) {
 358         if (obj1 == obj2) {
 359             return true; // object references are equal
 360         }
 361         if (obj1 == null) {
 362             return false; // obj2 was not false
 363         }
 364         if (obj1.getClass().isArray() &&
 365             obj2.getClass().isArray()) {
 366             return arrayEquals(obj1, obj2);
 367         }
 368         return (obj1.equals(obj2));
 369     }
 370 
 371     /**
 372      * Determines whether two arrays are equal by comparing each of their
 373      * elements using {@code Object.equals()}.
 374      */
 375     private static boolean arrayEquals(Object a1, Object a2) {
 376         int len;
 377         if ((len = Array.getLength(a1)) != Array.getLength(a2))
 378             return false;
 379 
 380         for (int j = 0; j < len; j++) {
 381             Object i1 = Array.get(a1, j);
 382             Object i2 = Array.get(a2, j);
 383             if (i1 == null || i2 == null) {
 384                 if (i1 != i2)
 385                     return false;
 386             } else if (!i1.equals(i2)) {
 387                 return false;
 388             }
 389         }
 390         return true;
 391     }
 392 
 393     /**
 394       * Adds a new value to this attribute.
 395       *<p>
 396       * By default, {@code Object.equals()} is used when comparing {@code attrVal}
 397       * with this attribute's values except when {@code attrVal} is an array.
 398       * For an array, each element of the array is checked using
 399       * {@code Object.equals()}.
 400       * A subclass may use schema information to determine equality.
 401       */
 402     public boolean add(Object attrVal) {
 403         if (isOrdered() || (find(attrVal) < 0)) {
 404             values.addElement(attrVal);
 405             return true;
 406         } else {
 407             return false;
 408         }
 409     }
 410 
 411     /**
 412       * Removes a specified value from this attribute.
 413       *<p>
 414       * By default, {@code Object.equals()} is used when comparing {@code attrVal}
 415       * with this attribute's values except when {@code attrVal} is an array.
 416       * For an array, each element of the array is checked using
 417       * {@code Object.equals()}.
 418       * A subclass may use schema information to determine equality.
 419       */
 420     public boolean remove(Object attrval) {
 421         // For the Java 2 platform, can just use "return removeElement(attrval);"
 422         // Need to do the following to handle null case
 423 
 424         int i = find(attrval);
 425         if (i >= 0) {
 426             values.removeElementAt(i);
 427             return true;
 428         }
 429         return false;
 430     }
 431 
 432     public void clear() {
 433         values.setSize(0);
 434     }
 435 
 436 //  ---- ordering methods
 437 


< prev index next >