• their have the same number of NC (AttributeTypeAndValue) - *
• each ATAVs are equals - *
• comparison of type are done case insensitive - *
• each value is equal, case sensitive - *
• their have the same number of NC (AttributeTypeAndValue) + *
• each ATAVs are equals + *
• comparison of type are done case insensitive + *
• each value is equal, case sensitive + *
• Order of ATAV is not important If the RDNs are not equals, a positive number is + * returned if the first RDN is greater, negative otherwise + * + * @param object + * @return 0 if both rdn are equals. -1 if the current RDN is inferior, 1 if + * the current Rdn is superior, UNDEFINED otherwise. + */ + public int compareTo( Object object ) + { + if ( object == null ) + { + return SUPERIOR; + } + + if ( object instanceof Rdn ) + { + Rdn rdn = ( Rdn ) object; + + if ( rdn.nbAtavs != nbAtavs ) + { + // We don't have the same number of ATAVs. The Rdn which + // has the higher number of Atav is the one which is + // superior + return nbAtavs - rdn.nbAtavs; + } + + switch ( nbAtavs ) + { + case 0: + return EQUAL; + + case 1: + return atav.compareTo( rdn.atav ); + + default: + // We have more than one value. We will + // go through all of them. + + // the types are already normalized and sorted in the atavs TreeSet + // so we could compare the 1st with the 1st, then the 2nd with the 2nd, etc. + Iterator localIterator = atavs.iterator(); + Iterator paramIterator = rdn.atavs.iterator(); + + while ( localIterator.hasNext() || paramIterator.hasNext() ) + { + if ( !localIterator.hasNext() ) + { + return SUPERIOR; + } + if ( !paramIterator.hasNext() ) + { + return INFERIOR; + } + + AttributeTypeAndValue localAtav = localIterator.next(); + AttributeTypeAndValue paramAtav = paramIterator.next(); + int result = localAtav.compareTo( paramAtav ); + if ( result != EQUAL ) + { + return result; + } + } + + return EQUAL; + } + } + else + { + return UNDEFINED; + } + } + + + /** + * @return a String representation of the RDN + */ + public String toString() + { + return normName == null ? "" : normName; + } + + + /** + * @return the user provided name + */ + public String getUpName() + { + return upName; + } + + + /** + * @return The normalized name + */ + public String getNormName() + { + return normName == null ? "" : normName; + } + + + /** + * Set the User Provided Name + * @param upName the User Provided dame + */ + public void setUpName( String upName ) + { + this.upName = upName; + } + + + /** + * @return Returns the nbAtavs. + */ + public int getNbAtavs() + { + return nbAtavs; + } + + + /** + * Return the unique AttributeTypeAndValue, or the first one of we have more + * than one + * + * @return The first AttributeTypeAndValue of this RDN + */ + public AttributeTypeAndValue getAtav() + { + switch ( nbAtavs ) + { + case 0: + return null; + + case 1: + return atav; + + default: + return ( ( TreeSet ) atavs ).first(); + } + } + + + /** + * Return the user provided type, or the first one of we have more than one (the lowest) + * + * @return The first user provided type of this RDN + */ + public String getUpType() + { + switch ( nbAtavs ) + { + case 0: + return null; + + case 1: + return atav.getUpType(); + + default: + return ( ( TreeSet ) atavs ).first().getUpType(); + } + } + + + /** + * Return the normalized type, or the first one of we have more than one (the lowest) + * + * @return The first normalized type of this RDN + */ + public String getNormType() + { + switch ( nbAtavs ) + { + case 0: + return null; + + case 1: + return atav.getNormType(); + + default: + return ( ( TreeSet ) atavs ).first().getNormType(); + } + } + + + /** + * Return the value, or the first one of we have more than one (the lowest) + * + * @return The first value of this RDN + */ + public Object getValue() + { + switch ( nbAtavs ) + { + case 0: + return null; + + case 1: + return atav.getNormValue().get(); + + default: + return ( ( TreeSet ) atavs ).first().getNormValue().get(); + } + } + + + /** + * Return the User Provided value + * + * @return The first User provided value of this RDN + */ + public String getUpValue() + { + switch ( nbAtavs ) + { + case 0: + return null; + + case 1: + return atav.getUpValue().getString(); + + default: + return ( ( TreeSet ) atavs ).first().getUpValue().getString(); + } + } - /** - * Return the unique AttributeTypeAndValue, or the first one of we have more - * than one - * - * @return The first AttributeTypeAndValue of this RDN - */ - public AttributeTypeAndValue getAtav() - { - switch ( nbAtavs ) - { - case 0: - return null; - - case 1: - return atav; - - default: - return ((TreeSet)atavs).first(); - } - } - - - /** - * Return the user provided type, or the first one of we have more than one (the lowest) - * - * @return The first user provided type of this RDN - */ - public String getUpType() - { - switch ( nbAtavs ) - { - case 0: - return null; - - case 1: - return atav.getUpType(); - - default: - return ((TreeSet)atavs).first().getUpType(); - } - } - - /** - * Return the normalized type, or the first one of we have more than one (the lowest) - * - * @return The first normalized type of this RDN - */ - public String getNormType() - { - switch ( nbAtavs ) - { - case 0: - return null; - - case 1: - return atav.getNormType(); - - default: - return ((TreeSet)atavs).first().getNormType(); - } - } - - /** - * Return the value, or the first one of we have more than one (the lowest) - * - * @return The first value of this RDN - */ - public Object getValue() - { - switch ( nbAtavs ) - { - case 0: - return null; - - case 1: - return atav.getNormValue().get(); - - default: - return ((TreeSet)atavs).first().getNormValue().get(); - } - } - - - /** - * Return the User Provided value - * - * @return The first User provided value of this RDN - */ - public String getUpValue() - { - switch ( nbAtavs ) - { - case 0: - return null; - - case 1: - return atav.getUpValue().getString(); - - default: - return ((TreeSet)atavs).first().getUpValue().getString(); - } - } - /** * Return the normalized value, or the first one of we have more than one (the lowest) * @@ -947,509 +952,511 @@ { case 0: return null; - + case 1: return atav.getNormValue().getString(); - + default: - return ((TreeSet)atavs).first().getNormalizedValue(); + return ( ( TreeSet ) atavs ).first().getNormalizedValue(); + } + } + + + /** + * Compares the specified Object with this Rdn for equality. Returns true if + * the given object is also a Rdn and the two Rdns represent the same + * attribute type and value mappings. The order of components in + * multi-valued Rdns is not significant. + * + * @param rdn + * Rdn to be compared for equality with this Rdn + * @return true if the specified object is equal to this Rdn + */ + public boolean equals( Object rdn ) + { + if ( this == rdn ) + { + return true; + } + + if ( !( rdn instanceof Rdn ) ) + { + return false; + } + + return compareTo( rdn ) == EQUAL; + } + + + /** + * Get the number of Attribute type and value of this Rdn + * + * @return The number of ATAVs in this Rdn + */ + public int size() + { + return nbAtavs; + } + + + /** + * Unescape the given string according to RFC 2253 If in form, a + * LDAP string representation asserted value can be obtained by replacing + * (left-to-right, non-recursively) each appearing in the as + * follows: replace with ; replace with + * ; replace with the octet indicated by the + * If in form, a BER representation can be obtained + * from converting each of the to the octet indicated + * by the + * + * @param value + * The value to be unescaped + * @return Returns a string value as a String, and a binary value as a byte + * array. + * @throws IllegalArgumentException - + * When an Illegal value is provided. + */ + public static Object unescapeValue( String value ) + { + if ( StringTools.isEmpty( value ) ) + { + return ""; + } + + char[] chars = value.toCharArray(); + + if ( chars[0] == '#' ) + { + if ( chars.length == 1 ) + { + // The value is only containing a # + return StringTools.EMPTY_BYTES; + } + + if ( ( chars.length % 2 ) != 1 ) + { + throw new IllegalArgumentException( "This value is not in hex form, we have an odd number of hex chars" ); + } + + // HexString form + byte[] hexValue = new byte[( chars.length - 1 ) / 2]; + int pos = 0; + + for ( int i = 1; i < chars.length; i += 2 ) + { + if ( StringTools.isHex( chars, i ) && StringTools.isHex( chars, i + 1 ) ) + { + hexValue[pos++] = StringTools.getHexValue( chars[i], chars[i + 1] ); + } + else + { + throw new IllegalArgumentException( "This value is not in hex form" ); + } + } + + return hexValue; + } + else + { + boolean escaped = false; + boolean isHex = false; + byte pair = -1; + int pos = 0; + + byte[] bytes = new byte[chars.length * 6]; + + for ( int i = 0; i < chars.length; i++ ) + { + if ( escaped ) + { + escaped = false; + + switch ( chars[i] ) + { + case '\\': + case '"': + case '+': + case ',': + case ';': + case '<': + case '>': + case '#': + case '=': + case ' ': + bytes[pos++] = ( byte ) chars[i]; + break; + + default: + if ( StringTools.isHex( chars, i ) ) + { + isHex = true; + pair = ( ( byte ) ( StringTools.getHexValue( chars[i] ) << 4 ) ); + } + + break; + } + } + else + { + if ( isHex ) + { + if ( StringTools.isHex( chars, i ) ) + { + pair += StringTools.getHexValue( chars[i] ); + bytes[pos++] = pair; + } + } + else + { + switch ( chars[i] ) + { + case '\\': + escaped = true; + break; + + // We must not have a special char + // Specials are : '"', '+', ',', ';', '<', '>', ' ', + // '#' and '=' + case '"': + case '+': + case ',': + case ';': + case '<': + case '>': + case '#': + if ( i != 0 ) + { + // '#' are allowed if not in first position + bytes[pos++] = '#'; + break; + } + case '=': + throw new IllegalArgumentException( "Unescaped special characters are not allowed" ); + + case ' ': + if ( ( i == 0 ) || ( i == chars.length - 1 ) ) + { + throw new IllegalArgumentException( "Unescaped special characters are not allowed" ); + } + else + { + bytes[pos++] = ' '; + break; + } + + default: + if ( ( chars[i] >= 0 ) && ( chars[i] < 128 ) ) + { + bytes[pos++] = ( byte ) chars[i]; + } + else + { + byte[] result = StringTools.charToBytes( chars[i] ); + System.arraycopy( result, 0, bytes, pos, result.length ); + pos += result.length; + } + + break; + } + } + } + } + + return StringTools.utf8ToString( bytes, pos ); + } + } + + + /** + * Transform a value in a String, accordingly to RFC 2253 + * + * @param value The attribute value to be escaped + * @return The escaped string value. + */ + public static String escapeValue( String value ) + { + if ( StringTools.isEmpty( value ) ) + { + return ""; + } + + char[] chars = value.toCharArray(); + char[] newChars = new char[chars.length * 3]; + int pos = 0; + + for ( int i = 0; i < chars.length; i++ ) + { + switch ( chars[i] ) + { + case ' ': + if ( ( i > 0 ) && ( i < chars.length - 1 ) ) + { + newChars[pos++] = chars[i]; + } + else + { + newChars[pos++] = '\\'; + newChars[pos++] = chars[i]; + } + + break; + + case '#': + if ( i != 0 ) + { + newChars[pos++] = chars[i]; + } + else + { + newChars[pos++] = '\\'; + newChars[pos++] = chars[i]; + } + + break; + + case '"': + case '+': + case ',': + case ';': + case '=': + case '<': + case '>': + case '\\': + newChars[pos++] = '\\'; + newChars[pos++] = chars[i]; + break; + + case 0x7F: + newChars[pos++] = '\\'; + newChars[pos++] = '7'; + newChars[pos++] = 'F'; + break; + + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + newChars[pos++] = '\\'; + newChars[pos++] = '0'; + newChars[pos++] = StringTools.dumpHex( ( byte ) ( chars[i] & 0x0F ) ); + break; + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + newChars[pos++] = '\\'; + newChars[pos++] = '1'; + newChars[pos++] = StringTools.dumpHex( ( byte ) ( chars[i] & 0x0F ) ); + break; + + default: + newChars[pos++] = chars[i]; + break; + + } + } + + return new String( newChars, 0, pos ); + } + + + /** + * Transform a value in a String, accordingly to RFC 2253 + * + * @param attrValue + * The attribute value to be escaped + * @return The escaped string value. + */ + public static String escapeValue( byte[] attrValue ) + { + if ( StringTools.isEmpty( attrValue ) ) + { + return ""; + } + + String value = StringTools.utf8ToString( attrValue ); + + return escapeValue( value ); + } + + + /** + * Gets the hashcode of this rdn. + * + * @see java.lang.Object#hashCode() + * @return the instance's hash code + */ + public int hashCode() + { + int result = 37; + + switch ( nbAtavs ) + { + case 0: + // An empty RDN + break; + + case 1: + // We have a single AttributeTypeAndValue + result = result * 17 + atav.hashCode(); + break; + + default: + // We have more than one AttributeTypeAndValue + + for ( AttributeTypeAndValue ata : atavs ) + { + result = result * 17 + ata.hashCode(); + } + + break; + } + + return result; + } + + + /** + * @see Externalizable#readExternal(ObjectInput)

+ * + * A RDN is composed of on to many ATAVs (AttributeType And Value). + * We should write all those ATAVs sequencially, following the + * structure : + * + *

• nbAtavs
• The number of ATAVs to write. Can't be 0. + *
• upName
• The User provided RDN + *
• normName
• The normalized RDN. It can be empty if the normalized + * name equals the upName. + *
• atavs
• + *

+ * For each ATAV :

+ *

• start
• The position of this ATAV in the upName string + *
• length
• The ATAV user provided length + *
• Call the ATAV write method
• The ATAV itself + * + * @param out The stream into which the serialized RDN will be put + * @throws IOException If the stream can't be written + */ + public void writeExternal( ObjectOutput out ) throws IOException + { + out.writeInt( nbAtavs ); + out.writeUTF( upName ); + + if ( upName.equals( normName ) ) + { + out.writeUTF( "" ); + } + else + { + out.writeUTF( normName ); + } + + out.writeInt( start ); + out.writeInt( length ); + + switch ( nbAtavs ) + { + case 0: + break; + + case 1: + out.writeObject( atav ); + break; + + default: + for ( AttributeTypeAndValue value : atavs ) + { + out.writeObject( value ); + } + + break; + } + } + + + /** + * @see Externalizable#readExternal(ObjectInput) + * + * We read back the data to create a new RDB. The structure + * read is exposed in the {@link Rdn#writeExternal(ObjectOutput)} + * method

+ * + * @param in The input stream from which the RDN will be read + * @throws IOException If we can't read from the input stream + * @throws ClassNotFoundException If we can't create a new RDN + */ + public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException + { + // Read the ATAV number + nbAtavs = in.readInt(); + + // Read the UPName + upName = in.readUTF(); + + // Read the normName + normName = in.readUTF(); + + if ( StringTools.isEmpty( normName ) ) + { + normName = upName; + } + + start = in.readInt(); + length = in.readInt(); + + switch ( nbAtavs ) + { + case 0: + atav = null; + break; + + case 1: + atav = ( AttributeTypeAndValue ) in.readObject(); + atavType = atav.getNormType(); + + break; + + default: + atavs = new TreeSet(); + + atavTypes = new MultiValueMap(); + + for ( int i = 0; i < nbAtavs; i++ ) + { + AttributeTypeAndValue value = ( AttributeTypeAndValue ) in.readObject(); + atavs.add( value ); + atavTypes.put( value.getNormType(), value ); + } + + atav = null; + atavType = null; + + break; } } - - - /** - * Compares the specified Object with this Rdn for equality. Returns true if - * the given object is also a Rdn and the two Rdns represent the same - * attribute type and value mappings. The order of components in - * multi-valued Rdns is not significant. - * - * @param rdn - * Rdn to be compared for equality with this Rdn - * @return true if the specified object is equal to this Rdn - */ - public boolean equals( Object rdn ) - { - if ( this == rdn ) - { - return true; - } - - if ( !( rdn instanceof Rdn ) ) - { - return false; - } - - return compareTo( rdn ) == EQUAL; - } - - - /** - * Get the number of Attribute type and value of this Rdn - * - * @return The number of ATAVs in this Rdn - */ - public int size() - { - return nbAtavs; - } - - - /** - * Unescape the given string according to RFC 2253 If in form, a - * LDAP string representation asserted value can be obtained by replacing - * (left-to-right, non-recursively) each appearing in the as - * follows: replace with ; replace with - * ; replace with the octet indicated by the - * If in form, a BER representation can be obtained - * from converting each of the to the octet indicated - * by the - * - * @param value - * The value to be unescaped - * @return Returns a string value as a String, and a binary value as a byte - * array. - * @throws IllegalArgumentException - - * When an Illegal value is provided. - */ - public static Object unescapeValue( String value ) - { - if ( StringTools.isEmpty( value ) ) - { - return ""; - } - - char[] chars = value.toCharArray(); - - if ( chars[0] == '#' ) - { - if ( chars.length == 1 ) - { - // The value is only containing a # - return StringTools.EMPTY_BYTES; - } - - if ( ( chars.length % 2 ) != 1 ) - { - throw new IllegalArgumentException( "This value is not in hex form, we have an odd number of hex chars" ); - } - - // HexString form - byte[] hexValue = new byte[( chars.length - 1 ) / 2]; - int pos = 0; - - for ( int i = 1; i < chars.length; i += 2 ) - { - if ( StringTools.isHex( chars, i ) && StringTools.isHex( chars, i + 1 ) ) - { - hexValue[pos++] = StringTools.getHexValue( chars[i], chars[i + 1] ); - } - else - { - throw new IllegalArgumentException( "This value is not in hex form" ); - } - } - - return hexValue; - } - else - { - boolean escaped = false; - boolean isHex = false; - byte pair = -1; - int pos = 0; - - byte[] bytes = new byte[chars.length * 6]; - - for ( int i = 0; i < chars.length; i++ ) - { - if ( escaped ) - { - escaped = false; - - switch ( chars[i] ) - { - case '\\': - case '"': - case '+': - case ',': - case ';': - case '<': - case '>': - case '#': - case '=': - case ' ': - bytes[pos++] = ( byte ) chars[i]; - break; - - default: - if ( StringTools.isHex( chars, i ) ) - { - isHex = true; - pair = ( (byte)( StringTools.getHexValue( chars[i] ) << 4 ) ); - } - - break; - } - } - else - { - if ( isHex ) - { - if ( StringTools.isHex( chars, i ) ) - { - pair += StringTools.getHexValue( chars[i] ); - bytes[pos++] = pair; - } - } - else - { - switch ( chars[i] ) - { - case '\\': - escaped = true; - break; - - // We must not have a special char - // Specials are : '"', '+', ',', ';', '<', '>', ' ', - // '#' and '=' - case '"': - case '+': - case ',': - case ';': - case '<': - case '>': - case '#': - if ( i != 0) - { - // '#' are allowed if not in first position - bytes[pos++] = '#'; - break; - } - case '=': - throw new IllegalArgumentException( "Unescaped special characters are not allowed" ); - - case ' ': - if ( ( i == 0 ) || ( i == chars.length - 1) ) - { - throw new IllegalArgumentException( "Unescaped special characters are not allowed" ); - } - else - { - bytes[pos++] = ' '; - break; - } - - default: - if ( ( chars[i] >= 0 ) && ( chars[i] < 128 ) ) - { - bytes[pos++] = (byte)chars[i]; - } - else - { - byte[] result = StringTools.charToBytes( chars[i] ); - System.arraycopy( result, 0, bytes, pos, result.length ); - pos += result.length; - } - - break; - } - } - } - } - - return StringTools.utf8ToString( bytes, pos ); - } - } - - - /** - * Transform a value in a String, accordingly to RFC 2253 - * - * @param value The attribute value to be escaped - * @return The escaped string value. - */ - public static String escapeValue( String value ) - { - if ( StringTools.isEmpty( value ) ) - { - return ""; - } - - char[] chars = value.toCharArray(); - char[] newChars = new char[chars.length * 3]; - int pos = 0; - - for ( int i = 0; i < chars.length; i++ ) - { - switch ( chars[i] ) - { - case ' ': - if ( ( i > 0 ) && ( i < chars.length - 1 ) ) - { - newChars[pos++] = chars[i]; - } - else - { - newChars[pos++] = '\\'; - newChars[pos++] = chars[i]; - } - - break; - - case '#': - if ( i != 0 ) - { - newChars[pos++] = chars[i]; - } - else - { - newChars[pos++] = '\\'; - newChars[pos++] = chars[i]; - } - - break; - - case '"': - case '+': - case ',': - case ';': - case '=': - case '<': - case '>': - case '\\': - newChars[pos++] = '\\'; - newChars[pos++] = chars[i]; - break; - - case 0x7F: - newChars[pos++] = '\\'; - newChars[pos++] = '7'; - newChars[pos++] = 'F'; - break; - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - newChars[pos++] = '\\'; - newChars[pos++] = '0'; - newChars[pos++] = StringTools.dumpHex( ( byte ) ( chars[i] & 0x0F ) ); - break; - - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - newChars[pos++] = '\\'; - newChars[pos++] = '1'; - newChars[pos++] = StringTools.dumpHex( ( byte ) ( chars[i] & 0x0F ) ); - break; - - default: - newChars[pos++] = chars[i]; - break; - - } - } - - return new String( newChars, 0, pos ); - } - - /** - * Transform a value in a String, accordingly to RFC 2253 - * - * @param attrValue - * The attribute value to be escaped - * @return The escaped string value. - */ - public static String escapeValue( byte[] attrValue ) - { - if ( StringTools.isEmpty( attrValue ) ) - { - return ""; - } - - String value = StringTools.utf8ToString( attrValue ); - - return escapeValue( value ); - } - - /** - * Gets the hashcode of this rdn. - * - * @see java.lang.Object#hashCode() - * @return the instance's hash code - */ - public int hashCode() - { - int result = 37; - - switch ( nbAtavs ) - { - case 0: - // An empty RDN - break; - - case 1: - // We have a single AttributeTypeAndValue - result = result * 17 + atav.hashCode(); - break; - - default: - // We have more than one AttributeTypeAndValue - - for ( AttributeTypeAndValue ata:atavs ) - { - result = result * 17 + ata.hashCode(); - } - - break; - } - - return result; - } - - - /** - * @see Externalizable#readExternal(ObjectInput)

- * - * A RDN is composed of on to many ATAVs (AttributeType And Value). - * We should write all those ATAVs sequencially, following the - * structure : - * - *

• nbAtavs
• The number of ATAVs to write. Can't be 0. - *
• upName
• The User provided RDN - *
• normName
• The normalized RDN. It can be empty if the normalized - * name equals the upName. - *
• atavs
• - *

- * For each ATAV :

- *

• start
• The position of this ATAV in the upName string - *
• length
• The ATAV user provided length - *
• Call the ATAV write method
• The ATAV itself - * - * @param out The stream into which the serialized RDN will be put - * @throws IOException If the stream can't be written - */ - public void writeExternal( ObjectOutput out ) throws IOException - { - out.writeInt( nbAtavs ); - out.writeUTF( upName ); - - if ( upName.equals( normName ) ) - { - out.writeUTF( "" ); - } - else - { - out.writeUTF( normName ); - } - - out.writeInt( start ); - out.writeInt( length ); - - switch ( nbAtavs ) - { - case 0 : - break; - - case 1 : - out.writeObject( atav ); - break; - - default : - for ( AttributeTypeAndValue value:atavs ) - { - out.writeObject( value ); - } - - break; - } - } - - - /** - * @see Externalizable#readExternal(ObjectInput) - * - * We read back the data to create a new RDB. The structure - * read is exposed in the {@link Rdn#writeExternal(ObjectOutput)} - * method

- * - * @param in The input stream from which the RDN will be read - * @throws IOException If we can't read from the input stream - * @throws ClassNotFoundException If we can't create a new RDN - */ - public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException - { - // Read the ATAV number - nbAtavs = in.readInt(); - - // Read the UPName - upName = in.readUTF(); - - // Read the normName - normName = in.readUTF(); - - if ( StringTools.isEmpty( normName ) ) - { - normName = upName; - } - - start = in.readInt(); - length = in.readInt(); - - switch ( nbAtavs ) - { - case 0 : - atav = null; - break; - - case 1 : - atav = (AttributeTypeAndValue)in.readObject(); - atavType = atav.getNormType(); - - break; - - default : - atavs = new TreeSet(); - - atavTypes = new MultiValueMap(); - - for ( int i = 0; i < nbAtavs; i++ ) - { - AttributeTypeAndValue value = (AttributeTypeAndValue)in.readObject(); - atavs.add( value ); - atavTypes.put( value.getNormType(), value ); - } - - atav = null; - atavType = null; - - break; - } - } }