You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2016/05/09 17:22:21 UTC

svn commit: r1743011 [7/13] - in /directory/shared/branches/shared-value: dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/request/ dsml/parser/src/main/java/org/apache/directory/api/dsmlv2/response/ dsml/parser/src/test/java/org/apache/direct...

Modified: directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java?rev=1743011&r1=1743010&r2=1743011&view=diff
==============================================================================
--- directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java (original)
+++ directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Ava.java Mon May  9 17:22:19 2016
@@ -43,15 +43,21 @@ import org.slf4j.LoggerFactory;
 
 
 /**
+ * <p>
  * A Attribute Type And Value, which is the basis of all Rdn. It contains a
  * type, and a value. The type must not be case sensitive. Superfluous leading
  * and trailing spaces MUST have been trimmed before. The value MUST be in UTF8
  * format, according to RFC 2253. If the type is in OID form, then the value
  * must be a hexadecimal string prefixed by a '#' character. Otherwise, the
  * string must respect the RC 2253 grammar.
- *
+ * </p>
+ * <p>
  * We will also keep a User Provided form of the AVA (Attribute Type And Value),
  * called upName.
+ * </p>
+ * <p>
+ * This class is immutable
+ * </p>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -117,6 +123,59 @@ public class Ava implements Externalizab
 
 
     /**
+     * Constructs new Ava using the provided SchemaManager and AVA
+     * 
+     * @param schemaManager The SchemaManager instance
+     * @param ava The AVA to copy
+     */
+    public Ava( SchemaManager schemaManager, Ava ava ) throws LdapInvalidDnException
+    {
+        upType = ava.upType;
+        
+        if ( ava.isSchemaAware() )
+        {
+            normType = ava.normType;
+            value = ava.value;
+        }
+        else
+        {
+            if ( schemaManager != null )
+            {
+                AttributeType attributeType = schemaManager.getAttributeType( ava.normType );
+                
+                if ( attributeType != null )
+                {
+                    normType = attributeType.getOid();
+
+                    try
+                    {
+                        value = new Value( attributeType, ava.value );
+                    }
+                    catch ( LdapInvalidAttributeValueException e )
+                    {
+                        throw new LdapInvalidDnException( e.getResultCode() );
+                    }
+                }
+                else
+                {
+                    normType = ava.normType;
+                    value = ava.value;
+                }
+            }
+            else
+            {
+                normType = ava.normType;
+                value = ava.value;
+            }
+        }
+        
+        upName = this.upType + '=' + ( this.value == null ? "" : this.value.getValue() );
+
+        hashCode();
+    }
+
+
+    /**
      * Construct an Ava containing a binary value.
      * <p>
      * Note that the upValue should <b>not</b> be null or empty, or resolve
@@ -182,6 +241,57 @@ public class Ava implements Externalizab
 
 
     /**
+     * Construct a schema aware Ava containing a binary value. The AttributeType
+     * and value will be normalized accordingly to the given SchemaManager.
+     * <p>
+     * Note that the upValue should <b>not</b> be null or empty, or resolve
+     * to an empty string after having trimmed it.
+     *
+     * @param schemaManager The SchemaManager instance
+     * @param upType The User Provided type
+     * @param upName the User Provided AVA
+     * @param upValue The User Provided binary value
+     * 
+     * @throws LdapInvalidDnException If the given type or value are invalid
+     */
+    public Ava( SchemaManager schemaManager, String upType, String upName, byte[] upValue ) throws LdapInvalidDnException
+    {
+        if ( schemaManager != null )
+        {
+            this.schemaManager = schemaManager;
+
+            try
+            {
+                attributeType = schemaManager.lookupAttributeTypeRegistry( upType );
+            }
+            catch ( LdapException le )
+            {
+                String message = I18n.err( I18n.ERR_04188 );
+                LOG.error( message );
+                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
+            }
+
+            try
+            {
+                createAva( schemaManager, upType, new Value( attributeType, upValue ) );
+            }
+            catch ( LdapInvalidAttributeValueException liave )
+            {
+                String message = I18n.err( I18n.ERR_04188 );
+                LOG.error( message );
+                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, liave );
+            }
+        }
+        else
+        {
+            createAva( upType, new Value( upValue ) );
+        }
+        
+        this.upName = upName;
+    }
+
+
+    /**
      * Construct an Ava with a String value.
      * <p>
      * Note that the upValue should <b>not</b> be null or empty, or resolve
@@ -246,6 +356,56 @@ public class Ava implements Externalizab
 
 
     /**
+     * Construct a schema aware Ava with a String value.
+     * <p>
+     * Note that the upValue should <b>not</b> be null or empty, or resolve
+     * to an empty string after having trimmed it.
+     *
+     * @param schemaManager The SchemaManager instance
+     * @param upType The User Provided type
+     * @param upName the User provided AVA
+     * @param upValue The User Provided String value
+     * 
+     * @throws LdapInvalidDnException If the given type or value are invalid
+     */
+    public Ava( SchemaManager schemaManager, String upType, String upName, String upValue ) throws LdapInvalidDnException
+    {
+        if ( schemaManager != null )
+        {
+            this.schemaManager = schemaManager;
+
+            try
+            {
+                attributeType = schemaManager.lookupAttributeTypeRegistry( upType );
+            }
+            catch ( LdapException le )
+            {
+                String message = I18n.err( I18n.ERR_04188 );
+                LOG.error( message );
+                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, le );
+            }
+
+            try
+            {
+                createAva( schemaManager, upType, new Value( attributeType, upValue ) );
+            }
+            catch ( LdapInvalidAttributeValueException liave )
+            {
+                String message = I18n.err( I18n.ERR_04188 );
+                LOG.error( message );
+                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, message, liave );
+            }
+        }
+        else
+        {
+            createAva( upType, new Value( upValue ) );
+        }
+        
+        this.upName = upName;
+    }
+
+
+    /**
      * Construct a schema aware Ava. The AttributeType and value will be checked accordingly
      * to the SchemaManager.
      * <p>
@@ -264,7 +424,7 @@ public class Ava implements Externalizab
         normType = attributeType.getOid();
         this.upType = upType;
         this.value = value;
-        upName = this.upType + '=' + ( value == null ? "" : Rdn.escapeValue( value.getString() ) );
+        upName = this.upType + '=' + ( value == null ? "" : Rdn.escapeValue( value.getValue() ) );
         hashCode();
     }
 
@@ -317,7 +477,7 @@ public class Ava implements Externalizab
 
         value = upValue;
 
-        upName = this.upType + '=' + ( value == null ? "" : Rdn.escapeValue( value.getString() ) );
+        upName = getEscaped();
         hashCode();
     }
 
@@ -346,7 +506,7 @@ public class Ava implements Externalizab
         this.upType = upType;
         this.normType = normType;
         this.value = value;
-        upName = this.upType + '=' + ( this.value == null ? "" : this.value.getString() );
+        upName = this.upType + '=' + ( this.value == null ? "" : this.value.getValue() );
 
         if ( schemaManager != null )
         {
@@ -450,7 +610,7 @@ public class Ava implements Externalizab
      * @throws LdapInvalidDnException If the Ava can't be normalized accordingly
      * to the given SchemaManager
      */
-    public void apply( SchemaManager schemaManager ) throws LdapInvalidDnException
+    private void apply( SchemaManager schemaManager ) throws LdapInvalidDnException
     {
         if ( schemaManager != null )
         {
@@ -487,8 +647,6 @@ public class Ava implements Externalizab
                 this.attributeType = tmpAttributeType;
             }
 
-            normType = tmpAttributeType.getOid();
-
             try
             {
                 value = new Value( tmpAttributeType, value );
@@ -539,17 +697,6 @@ public class Ava implements Externalizab
 
 
     /**
-     * Get the normalized Name of a Ava
-     *
-     * @return The name
-     */
-    public String getNormName()
-    {
-        return normalize();
-    }
-
-
-    /**
      * Get the user provided form of this attribute type and value
      *
      * @return The user provided form of this ava
@@ -558,6 +705,697 @@ public class Ava implements Externalizab
     {
         return upName;
     }
+    
+    
+    /**
+     * @return The Ava as an escaped String
+     */
+    public String getEscaped()
+    {
+        StringBuilder sb = new StringBuilder();
+        
+        sb.append( getType() );
+        sb.append( '=' );
+        
+        if ( value == null )
+        {
+            return sb.toString();
+        }
+        
+        byte[] bytes = value.getBytes();
+        
+        if ( Strings.isEmpty( bytes ) )
+        {
+            return sb.toString();
+        }
+        
+        boolean leadChar = true;
+        
+        for ( int pos = 0; pos < bytes.length; pos++  )
+        {
+            boolean trailChar = pos == bytes.length - 1;
+            byte b = bytes[pos];
+
+            switch ( b )
+            {
+                case 0x00 :
+                    sb.append( "\\00" );
+                    break;
+
+                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 :
+                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 :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                case 0x20 :
+                    if ( leadChar || trailChar )
+                    {
+                        sb.append( "\\ " );
+                    }
+                    else
+                    {
+                        sb.append( ( char ) b );
+                    }
+                    
+                    break;
+                    
+                case 0x21 :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                    
+                case 0x22 :
+                    sb.append( "\\\"" );
+                    break;
+
+                case 0x23 :
+                    if ( leadChar )
+                    {
+                        sb.append( "\\#" );
+                    }
+                    else
+                    {
+                        sb.append( '#' );
+                    }
+                    
+                    break;
+
+                case 0x24 :
+                case 0x25 :
+                case 0x26 :
+                case 0x27 :
+                case 0x28 :
+                case 0x29 :
+                case 0x2A :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                case 0x2B :
+                    sb.append( "\\+" );
+                    break;
+
+                case 0x2C :
+                    sb.append( "\\," );
+                    break;
+
+                case 0x2D :
+                case 0x2E :
+                case 0x2F :
+                case 0x30 :
+                case 0x31 :
+                case 0x32 :
+                case 0x33 :
+                case 0x34 :
+                case 0x35 :
+                case 0x36 :
+                case 0x37 :
+                case 0x38 :
+                case 0x39 :
+                case 0x3A :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                case 0x3B :
+                    sb.append( "\\;" );
+                    break;
+
+                case 0x3C :
+                    sb.append( "\\<" );
+                    break;
+
+                case 0x3D :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                case 0x3E :
+                    sb.append( "\\>" );
+                    break;
+                
+                case 0x3F :
+                case 0x40 :
+                case 0x41 :
+                case 0x42 :
+                case 0x43 :
+                case 0x44 :
+                case 0x45 :
+                case 0x46 :
+                case 0x47 :
+                case 0x48 :
+                case 0x49 :
+                case 0x4A :
+                case 0x4B :
+                case 0x4C :
+                case 0x4D :
+                case 0x4E :
+                case 0x4F :
+                case 0x50 :
+                case 0x51 :
+                case 0x52 :
+                case 0x53 :
+                case 0x54 :
+                case 0x55 :
+                case 0x56 :
+                case 0x57 :
+                case 0x58 :
+                case 0x59 :
+                case 0x5A :
+                case 0x5B :
+                    sb.append( ( char ) b );
+                    break;
+                    
+                case 0x5C :
+                    sb.append( "\\\\" );
+                    break;
+
+                case 0x5D :
+                case 0x5E :
+                case 0x5F :
+                case 0x60 :
+                case 0x61 :
+                case 0x62 :
+                case 0x63 :
+                case 0x64 :
+                case 0x65 :
+                case 0x66 :
+                case 0x67 :
+                case 0x68 :
+                case 0x69 :
+                case 0x6A :
+                case 0x6B :
+                case 0x6C :
+                case 0x6D :
+                case 0x6E :
+                case 0x6F :
+                case 0x70 :
+                case 0x71 :
+                case 0x72 :
+                case 0x73 :
+                case 0x74 :
+                case 0x75 :
+                case 0x76 :
+                case 0x77 :
+                case 0x78 :
+                case 0x79 :
+                case 0x7A :
+                case 0x7B :
+                case 0x7C :
+                case 0x7D :
+                case 0x7E :
+                case 0x7F :
+                    sb.append( ( char ) b );
+                    break;
+
+                // Between 0x80 and 0xC1, this is an octet
+                case ( byte ) 0x80 :
+                case ( byte ) 0x81 :
+                case ( byte ) 0x82 :
+                case ( byte ) 0x83 :
+                case ( byte ) 0x84 :
+                case ( byte ) 0x85 :
+                case ( byte ) 0x86 :
+                case ( byte ) 0x87 :
+                case ( byte ) 0x88 :
+                case ( byte ) 0x89 :
+                case ( byte ) 0x8A :
+                case ( byte ) 0x8B :
+                case ( byte ) 0x8C :
+                case ( byte ) 0x8D :
+                case ( byte ) 0x8E :
+                case ( byte ) 0x8F :
+                case ( byte ) 0x90 :
+                case ( byte ) 0x91 :
+                case ( byte ) 0x92 :
+                case ( byte ) 0x93 :
+                case ( byte ) 0x94 :
+                case ( byte ) 0x95 :
+                case ( byte ) 0x96 :
+                case ( byte ) 0x97 :
+                case ( byte ) 0x98 :
+                case ( byte ) 0x99 :
+                case ( byte ) 0x9A :
+                case ( byte ) 0x9B :
+                case ( byte ) 0x9C :
+                case ( byte ) 0x9D :
+                case ( byte ) 0x9E :
+                case ( byte ) 0x9F :
+                case ( byte ) 0xA0 :
+                case ( byte ) 0xA1 :
+                case ( byte ) 0xA2 :
+                case ( byte ) 0xA3 :
+                case ( byte ) 0xA4 :
+                case ( byte ) 0xA5 :
+                case ( byte ) 0xA6 :
+                case ( byte ) 0xA7 :
+                case ( byte ) 0xA8 :
+                case ( byte ) 0xA9 :
+                case ( byte ) 0xAA :
+                case ( byte ) 0xAB :
+                case ( byte ) 0xAC :
+                case ( byte ) 0xAD :
+                case ( byte ) 0xAE :
+                case ( byte ) 0xAF :
+                case ( byte ) 0xB0 :
+                case ( byte ) 0xB1 :
+                case ( byte ) 0xB2 :
+                case ( byte ) 0xB3 :
+                case ( byte ) 0xB4 :
+                case ( byte ) 0xB5 :
+                case ( byte ) 0xB6 :
+                case ( byte ) 0xB7 :
+                case ( byte ) 0xB8 :
+                case ( byte ) 0xB9 :
+                case ( byte ) 0xBA :
+                case ( byte ) 0xBB :
+                case ( byte ) 0xBC :
+                case ( byte ) 0xBD :
+                case ( byte ) 0xBE :
+                case ( byte ) 0xBF :
+                case ( byte ) 0xC0 :
+                case ( byte ) 0xC1 :
+                    sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    break;
+
+                // Between 0xC2 and 0xDF, we may have a UTF-2 char
+                case ( byte ) 0xC2 :
+                case ( byte ) 0xC3 :
+                case ( byte ) 0xC4 :
+                case ( byte ) 0xC5 :
+                case ( byte ) 0xC6 :
+                case ( byte ) 0xC7 :
+                case ( byte ) 0xC8 :
+                case ( byte ) 0xC9 :
+                case ( byte ) 0xCA :
+                case ( byte ) 0xCB :
+                case ( byte ) 0xCC :
+                case ( byte ) 0xCD :
+                case ( byte ) 0xCE :
+                case ( byte ) 0xCF :
+                case ( byte ) 0xD0 :
+                case ( byte ) 0xD1 :
+                case ( byte ) 0xD2 :
+                case ( byte ) 0xD3 :
+                case ( byte ) 0xD4 :
+                case ( byte ) 0xD5 :
+                case ( byte ) 0xD6 :
+                case ( byte ) 0xD7 :
+                case ( byte ) 0xD8 :
+                case ( byte ) 0xD9 :
+                case ( byte ) 0xDA :
+                case ( byte ) 0xDB :
+                case ( byte ) 0xDC :
+                case ( byte ) 0xDD :
+                case ( byte ) 0xDE :
+                case ( byte ) 0xDF :
+                    // UTF2, if the following byte is in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
+                        {
+                            // This is an UTF-2 char
+                            sb.append( Strings.utf8ToString( bytes, pos, 2 ) );
+                            pos++;
+                        }
+                        else
+                        {
+                            // Not an UTF-2
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        }
+                    }
+                
+                    break;
+
+                case ( byte ) 0xE0 :
+                    // May be an UTF-3, if the next byte is in [0xA0-0xBF], followed by a byte in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 2 )
+                    {
+                        // We only have 2 bytes : not an UTF-3
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x00A0 ) && ( b2 <= 0x00BF ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                // UTF-3
+                                sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
+                                pos += 2;
+                            }
+                            else
+                            {
+                                // Not an UTF-3, dump one bytes
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-3 : dump two byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        }
+                    }
+                    
+                    break;
+                    
+
+                // Between E1 and EC, this may be an UTF-3 if the next two bytes are between 0x80 and 0xBF
+                case ( byte ) 0xE1 :
+                case ( byte ) 0xE2 :
+                case ( byte ) 0xE3 :
+                case ( byte ) 0xE4 :
+                case ( byte ) 0xE5 :
+                case ( byte ) 0xE6 :
+                case ( byte ) 0xE7 :
+                case ( byte ) 0xE8 :
+                case ( byte ) 0xE9 :
+                case ( byte ) 0xEA :
+                case ( byte ) 0xEB :
+                case ( byte ) 0xEC :
+                case ( byte ) 0xEE :
+                case ( byte ) 0xEF :
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 2 )
+                    {
+                        // We only have 2 bytes : not an UTF-3
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                // UTF-3
+                                sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
+                                pos += 2;
+                            }
+                            else
+                            {
+                                // Not an UTF-3, dump one byte
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-3 : dump one byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            pos++;
+                        }
+                    }
+                    
+                    break;
+
+                case ( byte ) 0xED :
+                    // May be an UTF-3 if the second byte is in [0x80-0x9F] and the third byte in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 2 )
+                    {
+                        // We only have 2 bytes : not an UTF-3
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0080 ) && ( b2 <= 0x009F ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                // UTF-3
+                                sb.append( Strings.utf8ToString( bytes, pos, 3 ) );
+                                pos += 2;
+                            }
+                            else
+                            {
+                                // Not an UTF-3, dump one byte
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-3 : dump one byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            pos++;
+                        }
+                    }
+                    
+                    break;
+
+                case ( byte ) 0xF0 :
+                    // May be an UTF-4 if the second byte is in [0x90-0xBF] followed by two bytes in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 3 )
+                    {
+                        // We only have 2 bytes : not an UTF-4
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0090 ) && ( b2 <= 0x00BF ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                int b4 = bytes[pos + 3] & 0x00FF;
+                                
+                                // Check that the forth byte is in between 0x80-0xBF
+                                if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
+                                {
+                                    // UTF-4
+                                    sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
+                                    pos += 3;
+                                }
+                                else
+                                {
+                                    // Not an UTF-4, dump one byte
+                                    sb.append( '\\' ).append( Strings.byteToString( b ) );
+                                }
+                            }
+                            else
+                            {
+                                // Not an UTF-4, dump one byte
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-4 : dump one byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            pos++;
+                        }
+                    }
+                    
+                    break;
+
+                case ( byte ) 0xF1 :
+                case ( byte ) 0xF2 :
+                case ( byte ) 0xF3 :
+                    // May be an UTF-4
+                    // May be an UTF-4 if it's followed by three bytes in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 3 )
+                    {
+                        // We only have 2 bytes : not an UTF-4
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0080 ) && ( b2 <= 0x00BF ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                int b4 = bytes[pos + 3] & 0x00FF;
+                                
+                                // Check that the forth byte is in between 0x80-0xBF
+                                if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
+                                {
+                                    // UTF-4
+                                    sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
+                                    pos += 3;
+                                }
+                                else
+                                {
+                                    // Not an UTF-4, dump one byte
+                                    sb.append( '\\' ).append( Strings.byteToString( b ) );
+                                }
+                            }
+                            else
+                            {
+                                // Not an UTF-4, dump one byte
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-4 : dump one byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            pos++;
+                        }
+                    }
+                    
+                    break;
+
+                case ( byte ) 0xF4 :
+                    // May be an UTF-4 if the second byte is in [0x80-0x8F] followed by two bytes in [0x80-0xBF]
+                    if ( trailChar )
+                    {
+                        // No next byte : this is an octet
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                        break;
+                    }
+                    
+                    if ( pos == bytes.length - 3 )
+                    {
+                        // We only have 2 bytes : not an UTF-4
+                        sb.append( '\\' ).append( Strings.byteToString( b ) );
+                    }
+                    else
+                    {
+                        int b2 = bytes[pos + 1] & 0x00FF;
+                        
+                        if ( ( b2 >= 0x0080 ) && ( b2 <= 0x008F ) )
+                        {
+                            int b3 = bytes[pos + 2] & 0x00FF;
+                            
+                            // Check that the third byte is in between 0x80-0xBF
+                            if ( ( b3 >= 0x0080 ) && ( b3 <= 0x00BF ) )
+                            {
+                                int b4 = bytes[pos + 3] & 0x00FF;
+                                
+                                // Check that the forth byte is in between 0x80-0xBF
+                                if ( ( b4 >= 0x0080 ) && ( b4 <= 0x00BF ) )
+                                {
+                                    // UTF-4
+                                    sb.append( Strings.utf8ToString( bytes, pos, 4 ) );
+                                    pos += 3;
+                                }
+                                else
+                                {
+                                    // Not an UTF-4, dump one byte
+                                    sb.append( '\\' ).append( Strings.byteToString( b ) );
+                                }
+                            }
+                            else
+                            {
+                                // Not an UTF-4, dump one byte
+                                sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            }
+                        }
+                        else
+                        {
+                            // Not an UTF-4 : dump one byte
+                            sb.append( '\\' ).append( Strings.byteToString( b ) );
+                            pos++;
+                        }
+                    }
+                    
+                    break;
+
+
+                default :
+                    // octet
+                    sb.append( '\\' ).append( Strings.byteToString( b ) );
+
+                    break;
+                    
+            }
+            
+            if ( leadChar )
+            {
+                leadChar = false;
+            }
+        }
+        
+        return sb.toString();
+    }
 
 
     /**
@@ -582,42 +1420,6 @@ public class Ava implements Externalizab
 
 
     /**
-     * A Normalized String representation of a Ava :
-     * <ul>
-     * <li>type is trimed and lowercased</li>
-     * <li>value is trimed and lowercased, and special characters are escaped if needed.</li>
-     * </ul>
-     *
-     * @return A normalized string representing an Ava
-     */
-    public String normalize()
-    {
-        if ( value.isHumanReadable() )
-        {
-            // The result will be gathered in a stringBuilder
-            StringBuilder sb = new StringBuilder();
-
-            // First, store the type and the '=' char
-            sb.append( normType ).append( '=' );
-
-            String normalizedValue = ( String ) value.getNormValue();
-
-            if ( ( normalizedValue != null ) && ( normalizedValue.length() > 0 ) )
-            {
-                sb.append( Rdn.escapeValue( normalizedValue ) );
-            }
-
-            return sb.toString();
-        }
-        else
-        {
-            return normType + "=#"
-                + Strings.dumpHexPairs( value.getBytes() );
-        }
-    }
-
-
-    /**
      * Gets the hashcode of this object.
      *
      * @see java.lang.Object#hashCode()
@@ -655,25 +1457,43 @@ public class Ava implements Externalizab
         Ava instance = ( Ava ) obj;
 
         // Compare the type
-        if ( normType == null )
+        if ( attributeType == null )
         {
-            if ( instance.normType != null )
+            if ( normType == null )
             {
-                return false;
+                if ( instance.normType != null )
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if ( !normType.equals( instance.normType ) )
+                {
+                    return false;
+                }
             }
         }
         else
         {
-            if ( !normType.equals( instance.normType ) )
+            if ( instance.getAttributeType() == null )
+            {
+                if ( ( schemaManager != null ) 
+                        && !attributeType.equals( schemaManager.getAttributeType( instance.getType() ) ) )
+                {
+                    return false;
+                }
+            }
+            else if ( !attributeType.equals( instance.getAttributeType() ) )
             {
                 return false;
             }
         }
 
         // Compare the values
-        if ( value.isNull() )
+        if ( ( value == null ) || value.isNull() )
         {
-            return instance.value.isNull();
+            return ( instance.value == null ) || instance.value.isNull();
         }
         else
         {
@@ -695,7 +1515,7 @@ public class Ava implements Externalizab
                     }
                     else
                     {
-                        return value.getString().equals( instance.value.getString() );
+                        return value.getValue().equals( instance.value.getValue() );
                     }
                 }
             }
@@ -947,14 +1767,14 @@ public class Ava implements Externalizab
      *     <b>isHR</b> Tells if the value is a String or not
      *   </li>
      * </ul>
-     * <br/>
+     * <br>
      * if the value is a String :
      * <ul>
      *   <li>
      *     <b>value</b> The value
      *   </li>
      * </ul>
-     * <br/>
+     * <br>
      * if the value is binary :
      * <ul>
      *   <li>
@@ -1110,7 +1930,7 @@ public class Ava implements Externalizab
     /**
      * Tells if the Ava is schema aware or not.
      * 
-     * @return true if the Ava is schema aware
+     * @return <tt>true</tt> if the Ava is schema aware
      */
     public boolean isSchemaAware()
     {
@@ -1131,9 +1951,9 @@ public class Ava implements Externalizab
     {
         int comp = 0;
 
-        if ( value.getNormValue() instanceof String )
+        if ( value.isHumanReadable() )
         {
-            comp = ( ( String ) value.getNormValue() ).compareTo( ( ( String ) that.value.getNormValue() ) );
+            comp = value.compareTo( that.value );
 
             return comp;
         }
@@ -1166,7 +1986,6 @@ public class Ava implements Externalizab
     /**
      * @see Comparable#compareTo(Object)
      */
-    @SuppressWarnings("unchecked")
     public int compareTo( Ava that )
     {
         if ( that == null )
@@ -1253,7 +2072,7 @@ public class Ava implements Externalizab
 
                 if ( comparator != null )
                 {
-                    comp = comparator.compare( value.getNormValue(), that.value.getNormValue() );
+                    comp = value.compareTo( that.value );
 
                     return comp;
                 }

Modified: directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java?rev=1743011&r1=1743010&r2=1743011&view=diff
==============================================================================
--- directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java (original)
+++ directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/ComplexDnParser.java Mon May  9 17:22:19 2016
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
 
 
 /**
@@ -43,13 +44,13 @@ import org.apache.directory.api.ldap.mod
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    /* No protection*/void parseDn( String name, List<Rdn> rdns ) throws LdapInvalidDnException
+    /* No protection*/void parseDn( SchemaManager schemaManager, String name, List<Rdn> rdns ) throws LdapInvalidDnException
     {
         AntlrDnParser dnParser = new AntlrDnParser( new AntlrDnLexer( new StringReader( name ) ) );
 
         try
         {
-            dnParser.relativeDistinguishedNames( rdns );
+            dnParser.relativeDistinguishedNames( schemaManager, rdns );
         }
         catch ( Exception e )
         {
@@ -66,13 +67,13 @@ import org.apache.directory.api.ldap.mod
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    /* No protection*/void parseRdn( String name, Rdn rdn ) throws LdapInvalidDnException
+    /* No protection*/void parseRdn( SchemaManager schemaManager, String name, Rdn rdn ) throws LdapInvalidDnException
     {
         AntlrDnParser dnParser = new AntlrDnParser( new AntlrDnLexer( new StringReader( name ) ) );
 
         try
         {
-            dnParser.relativeDistinguishedName( rdn );
+            dnParser.relativeDistinguishedName( schemaManager, rdn );
         }
         catch ( Exception e )
         {

Modified: directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java?rev=1743011&r1=1743010&r2=1743011&view=diff
==============================================================================
--- directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java (original)
+++ directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/Dn.java Mon May  9 17:22:19 2016
@@ -26,23 +26,14 @@ import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
 
 import org.apache.commons.collections.list.UnmodifiableList;
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
-import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer;
 import org.apache.directory.api.util.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -105,12 +96,6 @@ public class Dn implements Iterable<Rdn>
     /** The user provided name */
     private String upName;
 
-    /** The normalized name */
-    private String normName;
-
-    /** The bytes representation of the normName */
-    private byte[] bytes;
-
     /** A null Dn */
     public static final Dn EMPTY_DN = new Dn();
 
@@ -181,7 +166,29 @@ public class Dn implements Iterable<Rdn>
     {
         this.schemaManager = schemaManager;
         upName = "";
-        normName = "";
+    }
+
+
+    /**
+     * Construct an empty Schema aware Dn object
+     * 
+     *  @param schemaManager The SchemaManager to use
+     */
+    public Dn( SchemaManager schemaManager, Dn dn ) throws LdapInvalidDnException
+    {
+        this.schemaManager = schemaManager;
+
+        if ( dn == null )
+        {
+            return;
+        }
+
+        for ( Rdn rdn : dn.rdns )
+        {
+            this.rdns.add( new Rdn( schemaManager, rdn ) );
+        }
+
+        toUpName();
     }
 
 
@@ -242,6 +249,7 @@ public class Dn implements Iterable<Rdn>
         StringBuilder sb = new StringBuilder();
         boolean valueExpected = false;
         boolean isFirst = true;
+        this.schemaManager = schemaManager;
 
         for ( String upRdn : upRdns )
         {
@@ -287,8 +295,7 @@ public class Dn implements Iterable<Rdn>
         
         try
         {
-            parseInternal( upName, rdns );
-            apply( schemaManager );
+            parseInternal( schemaManager, upName, rdns );
         }
         catch ( LdapInvalidDnException e )
         {
@@ -305,26 +312,6 @@ public class Dn implements Iterable<Rdn>
 
 
     /**
-     * Create a schema aware Dn while deserializing it.
-     * <br/>
-     * Note : this constructor is used only by the deserialization method.
-     * 
-     * @param schemaManager the schema manager
-     * @param upName The user provided name
-     * @param normName the normalized name
-     * @param rdns the list of RDNs for this Dn
-     */
-    /* No protection */Dn( SchemaManager schemaManager, String upName, String normName, Rdn... rdns )
-    {
-        this.schemaManager = schemaManager;
-        this.upName = upName;
-        this.normName = normName;
-        bytes = Strings.getBytesUtf8Ascii( upName );
-        this.rdns = Arrays.asList( rdns );
-    }
-
-
-    /**
      * Creates a Dn from a list of Rdns.
      *
      * @param rdns the list of Rdns to be used for the Dn
@@ -342,7 +329,6 @@ public class Dn implements Iterable<Rdn>
             this.rdns.add( rdn );
         }
 
-        apply( null );
         toUpName();
     }
 
@@ -368,7 +354,6 @@ public class Dn implements Iterable<Rdn>
 
         rdns.add( 0, rdn );
 
-        apply( dn.schemaManager );
         toUpName();
     }
 
@@ -389,10 +374,16 @@ public class Dn implements Iterable<Rdn>
 
         for ( Rdn rdn : rdns )
         {
-            this.rdns.add( rdn );
+            if ( rdn.isSchemaAware() )
+            {
+                this.rdns.add( rdn );
+            }
+            else
+            {
+                this.rdns.add( new Rdn( schemaManager, rdn ) );
+            }
         }
 
-        apply( schemaManager );
         toUpName();
     }
 
@@ -474,6 +465,33 @@ public class Dn implements Iterable<Rdn>
     {
         return ( upName == null ? "" : upName );
     }
+    
+    
+    /**
+     * @return The RDN as an escaped String
+     */
+    public String getEscaped()
+    {
+        StringBuilder sb = new StringBuilder();
+        
+        boolean isFirst = true;
+        
+        for ( Rdn rdn : rdns )
+        {
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                sb.append( ',' );
+            }
+            
+            sb.append( rdn.getEscaped() );
+        }
+        
+        return sb.toString();
+    }
 
 
     /**
@@ -490,28 +508,6 @@ public class Dn implements Iterable<Rdn>
 
 
     /**
-     * Get the normalized Dn. If the Dn is schema aware, the AttributeType
-     * will be represented using its OID :<br/>
-     * <pre>
-     * Dn dn = new Dn( schemaManager, "ou = Example , ou = com" );
-     * assert( "2.5.4.11=example,2.5.4.11=com".equals( dn.getNormName ) );
-     * </pre>
-     * Otherwise, it will return a Dn with the AttributeType in lower case
-     * and the value trimmed : <br/>
-     * <pre>
-     * Dn dn = new Dn( " CN = A   Test " );
-     * assertEquals( "cn=A   Test", dn.getNormName() );
-     * </pre>
-     *
-     * @return The normalized Dn as a String
-     */
-    public String getNormName()
-    {
-        return normName;
-    }
-
-
-    /**
      * Get the number of RDNs present in the DN
      * @return The umber of RDNs in the DN
      */
@@ -522,30 +518,6 @@ public class Dn implements Iterable<Rdn>
 
 
     /**
-     * Get the number of bytes necessary to store this Dn
-
-     * @param dn The Dn.
-     * @return A integer, which is the size of the UTF-8 byte array
-     */
-    public static int getNbBytes( Dn dn )
-    {
-        return dn.bytes == null ? 0 : dn.bytes.length;
-    }
-
-
-    /**
-     * Get an UTF-8 representation of the normalized form of the Dn
-     *
-     * @param dn The Dn.
-     * @return A byte[] representation of the Dn
-     */
-    public static byte[] getBytes( Dn dn )
-    {
-        return dn == null ? null : dn.bytes;
-    }
-
-
-    /**
      * Tells if the current Dn is a parent of another Dn.<br>
      * For instance, <b>dc=com</b> is a ancestor
      * of <b>dc=example, dc=com</b>
@@ -797,7 +769,6 @@ public class Dn implements Iterable<Rdn>
         }
 
         newDn.toUpName();
-        newDn.apply( schemaManager, true );
 
         return newDn;
     }
@@ -878,7 +849,6 @@ public class Dn implements Iterable<Rdn>
         }
 
         newDn.toUpName();
-        newDn.apply( schemaManager, true );
 
         return newDn;
     }
@@ -904,14 +874,11 @@ public class Dn implements Iterable<Rdn>
         {
             if ( clonedDn.size() != 0 )
             {
-                clonedDn.normName = suffix.getNormName() + "," + normName;
-                clonedDn.bytes = Strings.getBytesUtf8Ascii( normName );
                 clonedDn.upName = suffix.getName() + "," + upName;
             }
         }
         else
         {
-            clonedDn.apply( schemaManager, true );
             clonedDn.toUpName();
         }
 
@@ -936,7 +903,6 @@ public class Dn implements Iterable<Rdn>
 
         clonedDn.rdns.add( 0, newRdn );
 
-        clonedDn.apply( schemaManager, true );
         clonedDn.toUpName();
 
         return clonedDn;
@@ -958,8 +924,7 @@ public class Dn implements Iterable<Rdn>
 
         Dn clonedDn = copy();
 
-        clonedDn.rdns.add( 0, newRdn );
-        clonedDn.apply( schemaManager, true );
+        clonedDn.rdns.add( 0, new Rdn( schemaManager, newRdn ) );
         clonedDn.toUpName();
 
         return clonedDn;
@@ -989,15 +954,6 @@ public class Dn implements Iterable<Rdn>
             newDn.rdns.add( rdns.get( i ) );
         }
 
-        try
-        {
-            newDn.apply( schemaManager, true );
-        }
-        catch ( LdapInvalidDnException e )
-        {
-            LOG.error( e.getMessage(), e );
-        }
-
         newDn.toUpName();
 
         return newDn;
@@ -1028,305 +984,46 @@ public class Dn implements Iterable<Rdn>
     @Override
     public boolean equals( Object obj )
     {
+        Dn other = null;
+        
         if ( obj instanceof String )
         {
-            return normName.equals( obj );
-        }
-        else if ( obj instanceof Dn )
-        {
-            Dn name = ( Dn ) obj;
-
-            if ( name.getNormName().equals( normName ) )
+            try
             {
-                return true;
+                other = new Dn( schemaManager, ( String ) obj );
             }
-
-            if ( name.size() != this.size() )
+            catch ( LdapInvalidDnException e )
             {
                 return false;
             }
-
-            for ( int i = 0; i < this.size(); i++ )
-            {
-                if ( !name.rdns.get( i ).equals( rdns.get( i ) ) )
-                {
-                    return false;
-                }
-            }
-
-            // All components matched so we return true
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-
-    /**
-     * Normalize the Ava
-     */
-    private static Ava atavOidToName( Ava atav, SchemaManager schemaManager )
-        throws LdapInvalidDnException
-    {
-        Map<String, OidNormalizer> oidsMap = schemaManager.getNormalizerMapping();
-        String type = Strings.trim( atav.getNormType() );
-
-        if ( ( type.startsWith( "oid." ) ) || ( type.startsWith( "OID." ) ) )
-        {
-            type = type.substring( 4 );
         }
-
-        if ( Strings.isNotEmpty( type ) )
+        else if ( obj instanceof Dn )
         {
-            if ( oidsMap == null )
-            {
-                return atav;
-            }
-
-            type = Strings.toLowerCaseAscii( type );
-
-            // Check that we have an existing AttributeType for this type
-            if ( !oidsMap.containsKey( type ) )
-            {
-                // No AttributeType : this is an error
-                String msg = I18n.err( I18n.ERR_04268_OID_NOT_FOUND, atav.getType() );
-                LOG.error( msg );
-                throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, msg );
-            }
-
-            OidNormalizer oidNormalizer = oidsMap.get( type );
-
-            if ( oidNormalizer != null )
-            {
-                try
-                {
-                    AttributeType attributeType = schemaManager.getAttributeType( type );
-                    if ( attributeType == null )
-                    {
-                        // Error should NOT be logged here as exception is thrown. Whoever catches
-                        // the exception should log the error. This exception is caught and ignored
-                        // in the relaxed mode, and it is in fact quite expected to happed for some
-                        // insane DN formats. Logging the error here will only polute the logfiles
-                        throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX,
-                            I18n.err( I18n.ERR_04460_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED, type ) );
-                    }
-                    Value atavValue = null;
-                    Value value = atav.getValue();
-                    
-                    if ( value.isHumanReadable() )
-                    {
-                        // Active Directory specifies syntax OIDs in attributeTypes, but it does not specify
-                        // any syntexes. Therefore attributeType.getSyntax() returns null. Assume human readable
-                        // attribute in such case.
-                        if ( attributeType.getSyntax() == null || attributeType.getSyntax().isHumanReadable() )
-                        {
-                            atavValue = new Value( attributeType, value.getString() );
-                        }
-                        else
-                        {
-                            // This is a binary variable, transaform the Value to a BinaryValye
-                            atavValue = new Value( attributeType, value.getBytes() );
-                        }
-                    }
-                    else
-                    {
-                        atavValue = new Value( attributeType, atav.getValue().getBytes() );
-                    }
-                    
-                    Ava newAva = new Ava(
-                        attributeType,
-                        atav.getType(),
-                        oidNormalizer.getAttributeTypeOid(),
-                        atavValue,
-                        atav.getName() );
-
-                    return newAva;
-                }
-                catch ( LdapException le )
-                {
-                    throw new LdapInvalidDnException( le.getMessage(), le );
-                }
-            }
-            else
-            {
-                // We don't have a normalizer for this OID : just do nothing.
-                return atav;
-            }
+            other = ( Dn ) obj;
         }
         else
         {
-            // The type is empty : this is not possible...
-            String msg = I18n.err( I18n.ERR_04209_EMPTY_TYPE_NOT_ALLOWED );
-            LOG.error( msg );
-            throw new LdapInvalidDnException( ResultCodeEnum.INVALID_DN_SYNTAX, msg );
-        }
-    }
-
-
-    /**
-     * Transform a Rdn by changing the value to its OID counterpart and
-     * normalizing the value accordingly to its type. We also sort the AVAs
-     *
-     * @param rdn The Rdn to modify.
-     * @param SchemaManager The schema manager
-     * @throws LdapInvalidDnException If the Rdn is invalid.
-     */
-    /** No qualifier */
-    static void rdnOidToName( Rdn rdn, SchemaManager schemaManager ) throws LdapInvalidDnException
-    {
-        // We have more than one ATAV for this Rdn. We will loop on all
-        // ATAVs
-        //Rdn rdnCopy = rdn.clone();
-        //rdn.clear();
-
-        if ( rdn.size() < 2 )
-        {
-            Ava newAtav = atavOidToName( rdn.getAva(), schemaManager );
-            rdn.replaceAva( newAtav, 0 );
+            return false;
         }
-        else
+        
+        if ( other.size() != this.size() )
         {
-            Set<String> sortedOids = new TreeSet<String>();
-            Map<String, Ava> avas = new HashMap<String, Ava>();
-
-            // Sort the OIDs
-            for ( Ava val : rdn )
-            {
-                Ava newAtav = atavOidToName( val, schemaManager );
-                String oid = newAtav.getAttributeType().getOid();
-                sortedOids.add( oid );
-                avas.put( oid, newAtav );
-            }
-
-            // And create the Rdn
-            int pos = 0;
-
-            for ( String oid : sortedOids )
-            {
-                rdn.replaceAva( avas.get( oid ), pos++ );
-            }
+            return false;
         }
-    }
 
-
-    /**
-     * Normalizes the Dn using the given the schema manager. If the flag is set to true,
-     * we will replace the inner SchemaManager by the provided one.
-     *
-     * @param schemaManager The schemaManagerto use to normalize the Dn
-     * @param force Tells if we should replace an existing SchemaManager by a new one
-     * @return The normalized Dn
-     * @throws LdapInvalidDnException If the Dn is invalid.
-     */
-    public Dn apply( SchemaManager schemaManager, boolean force ) throws LdapInvalidDnException
-    {
-        if ( ( this.schemaManager == null ) || force )
+        for ( int i = 0; i < this.size(); i++ )
         {
-            this.schemaManager = schemaManager;
-
-            if ( this.schemaManager != null )
+            if ( !other.rdns.get( i ).equals( rdns.get( i ) ) )
             {
-                synchronized ( this )
-                {
-                    if ( size() == 0 )
-                    {
-                        bytes = null;
-                        normName = "";
-
-                        return this;
-                    }
-
-                    StringBuilder sb = new StringBuilder();
-                    boolean isFirst = true;
-
-                    for ( Rdn rdn : rdns )
-                    {
-                        rdn.apply( schemaManager );
-
-                        if ( isFirst )
-                        {
-                            isFirst = false;
-                        }
-                        else
-                        {
-                            sb.append( ',' );
-                        }
-
-                        sb.append( rdn.getNormName() );
-                    }
-
-                    String newNormName = sb.toString();
-
-                    if ( ( normName == null ) || !normName.equals( newNormName ) )
-                    {
-                        bytes = Strings.getBytesUtf8Ascii( newNormName );
-                        normName = newNormName;
-                    }
-                }
-            }
-            else
-            {
-                if ( rdns.size() == 0 )
-                {
-                    bytes = null;
-                    normName = "";
-                }
-                else
-                {
-                    StringBuffer sb = new StringBuffer();
-                    boolean isFirst = true;
-
-                    for ( Rdn rdn : rdns )
-                    {
-                        if ( isFirst )
-                        {
-                            isFirst = false;
-                        }
-                        else
-                        {
-                            sb.append( ',' );
-                        }
-
-                        sb.append( rdn.getNormName() );
-                    }
-
-                    String newNormName = sb.toString();
-
-                    if ( ( normName == null ) || !normName.equals( newNormName ) )
-                    {
-                        bytes = Strings.getBytesUtf8Ascii( newNormName );
-                        normName = newNormName;
-                    }
-                }
+                return false;
             }
         }
 
-        return this;
-    }
-
-
-    /**
-     * Normalizes the Dn using the given the schema manager, unless the Dn is already normalized
-     *
-     * @param schemaManager The schemaManagerto use to normalize the Dn
-     * @return The normalized Dn
-     * @throws LdapInvalidDnException If the Dn is invalid.
-     */
-    public Dn apply( SchemaManager schemaManager ) throws LdapInvalidDnException
-    {
-        if ( this.schemaManager != null )
-        {
-            return this;
-        }
-        else
-        {
-            return apply( schemaManager, true );
-        }
+        // All components matched so we return true
+        return true;
     }
 
-
+    
     /**
      * Tells if the Dn is schema aware
      *
@@ -1389,7 +1086,31 @@ public class Dn implements Iterable<Rdn>
 
         try
         {
-            parseInternal( name, dn.rdns );
+            parseInternal( null, name, dn.rdns );
+            return true;
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * Check if a DistinguishedName is syntactically valid.
+     *
+     * @param schemaManager The SchemaManager to use
+     * @param dn The Dn to validate
+     * @return <code>true></code> if the Dn is valid, <code>false</code>
+     * otherwise
+     */
+    public static boolean isValid( SchemaManager schemaManager, String name )
+    {
+        Dn dn = new Dn();
+
+        try
+        {
+            parseInternal( schemaManager, name, dn.rdns );
             return true;
         }
         catch ( LdapInvalidDnException e )
@@ -1406,16 +1127,16 @@ public class Dn implements Iterable<Rdn>
      * @param rdns The list that will contain the RDNs
      * @throws LdapInvalidDnException If the Dn is invalid
      */
-    private static void parseInternal( String name, List<Rdn> rdns ) throws LdapInvalidDnException
+    private static void parseInternal( SchemaManager schemaManager, String name, List<Rdn> rdns ) throws LdapInvalidDnException
     {
         try
         {
-            FastDnParser.parseDn( name, rdns );
+            FastDnParser.parseDn( schemaManager, name, rdns );
         }
         catch ( TooComplexDnException e )
         {
             rdns.clear();
-            new ComplexDnParser().parseDn( name, rdns );
+            new ComplexDnParser().parseDn( schemaManager, name, rdns );
         }
     }
 
@@ -1428,19 +1149,6 @@ public class Dn implements Iterable<Rdn>
         // Read the UPName
         upName = in.readUTF();
 
-        // Read the NormName
-        normName = in.readUTF();
-
-        if ( normName.length() == 0 )
-        {
-            // As the normName is equal to the upName,
-            // we didn't saved the nbnormName on disk.
-            // restore it by copying the upName.
-            normName = upName;
-        }
-
-        bytes = Strings.getBytesUtf8Ascii( normName );
-        
         // Read the RDNs. Is it's null, the number will be -1.
         int nbRdns = in.readInt();
 
@@ -1470,16 +1178,6 @@ public class Dn implements Iterable<Rdn>
         // Write the UPName
         out.writeUTF( upName );
 
-        // Write the NormName if different
-        if ( upName.equals( normName ) )
-        {
-            out.writeUTF( "" );
-        }
-        else
-        {
-            out.writeUTF( normName );
-        }
-
         // Write the RDNs.
         // First the number of RDNs
         out.writeInt( size() );

Modified: directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java?rev=1743011&r1=1743010&r2=1743011&view=diff
==============================================================================
--- directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java (original)
+++ directory/shared/branches/shared-value/ldap/model/src/main/java/org/apache/directory/api/ldap/model/name/FastDnParser.java Mon May  9 17:22:19 2016
@@ -23,10 +23,10 @@ package org.apache.directory.api.ldap.mo
 import java.util.List;
 
 import org.apache.directory.api.i18n.I18n;
-import org.apache.directory.api.ldap.model.entry.Value;
 import org.apache.directory.api.ldap.model.exception.LdapException;
 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Position;
 
 
@@ -50,7 +50,24 @@ import org.apache.directory.api.util.Pos
     /* No protection*/static Dn parse( String name ) throws LdapException
     {
         Dn dn = new Dn();
-        parseDn( name, dn );
+        parseDn( null, name, dn );
+        
+        return dn;
+    }
+
+
+    /**
+     * Parses a Dn from a String
+     *
+     * @param name The Dn to parse
+     * @return A valid Dn
+     * @throws org.apache.directory.api.ldap.model.exception.LdapException If the Dn was invalid
+     */
+    /* No protection*/static Dn parse( SchemaManager schemaManager, String name ) throws LdapException
+    {
+        Dn dn = new Dn( schemaManager );
+        parseDn( schemaManager, name, dn );
+        
         return dn;
     }
 
@@ -63,15 +80,14 @@ import org.apache.directory.api.util.Pos
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    /* No protection*/static void parseDn( String name, Dn dn ) throws LdapInvalidDnException
+    /* No protection*/static void parseDn( SchemaManager schemaManager, String name, Dn dn ) throws LdapInvalidDnException
     {
-        parseDn( name, dn.rdns );
+        parseDn( schemaManager, name, dn.rdns );
         dn.setUpName( name );
-        dn.apply( null );
     }
 
 
-    /* No protection*/static void parseDn( String name, List<Rdn> rdns ) throws LdapInvalidDnException
+    /* No protection*/static void parseDn( SchemaManager schemaManager, String name, List<Rdn> rdns ) throws LdapInvalidDnException
     {
         if ( ( name == null ) || ( name.trim().length() == 0 ) )
         {
@@ -87,8 +103,8 @@ import org.apache.directory.api.util.Pos
 
         while ( true )
         {
-            Rdn rdn = new Rdn();
-            parseRdnInternal( name, pos, rdn );
+            Rdn rdn = new Rdn( schemaManager );
+            parseRdnInternal( schemaManager, name, pos, rdn );
             rdns.add( rdn );
 
             if ( !hasMoreChars( pos ) )
@@ -122,7 +138,7 @@ import org.apache.directory.api.util.Pos
      * 
      * @throws LdapInvalidDnException the invalid name exception
      */
-    /* No protection*/static void parseRdn( String name, Rdn rdn ) throws LdapInvalidDnException
+    /* No protection*/static void parseRdn( SchemaManager schemaManager, String name, Rdn rdn ) throws LdapInvalidDnException
     {
         if ( name == null || name.length() == 0 )
         {
@@ -138,11 +154,11 @@ import org.apache.directory.api.util.Pos
         pos.start = 0;
         pos.length = name.length();
 
-        parseRdnInternal( name, pos, rdn );
+        parseRdnInternal( schemaManager, name, pos, rdn );
     }
 
 
-    private static void parseRdnInternal( String name, Position pos, Rdn rdn ) throws LdapInvalidDnException
+    private static void parseRdnInternal( SchemaManager schemaManager, String name, Position pos, Rdn rdn ) throws LdapInvalidDnException
     {
         int rdnStart = pos.start;
         char[] chars = name.toCharArray();
@@ -172,11 +188,11 @@ import org.apache.directory.api.util.Pos
 
         String upName = name.substring( rdnStart, pos.start );
 
-        Ava ava = new Ava( type, type, new Value( upValue ), upName );
+        Ava ava = new Ava( schemaManager, type, upValue );
         rdn.addAVA( null, ava );
 
         rdn.setUpName( upName );
-        rdn.normalize();
+        rdn.hashCode();
     }